-
// groundnet.cxx - Implimentation of the FlightGear airport ground handling code
//
// Written by Durk Talsma, started June 2005.
#include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx>
+#include <ATC/atc_mgr.hxx>
+
#include <Scenery/scenery.hxx>
#include "groundnetwork.hxx"
SGGeodesy::inverse(start->getGeod(), end->getGeod(), heading, az2, length);
double coveredDistance = length * 0.5;
SGGeodesy::direct(start->getGeod(), heading, coveredDistance, center, az2);
+ //start->setElevation(elevation);
+ //end->setElevation(elevation);
//cerr << "Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
}
return true;
};
+
void FGTaxiRoute::rewind(int route)
{
int currPoint;
count = 0;
currTraffic = activeTraffic.begin();
group = 0;
+ networkInitialized = false;
}
FGGroundNetwork::~FGGroundNetwork()
{
+ //cerr << "Running Groundnetwork Destructor " << endl;
+ bool saveData = false;
+ ofstream cachefile;
+ if (fgGetBool("/sim/ai/groundnet-cache")) {
+ SGPath cacheData(fgGetString("/sim/fg-home"));
+ cacheData.append("ai");
+ string airport = parent->getId();
+
+ if ((airport) != "") {
+ char buffer[128];
+ ::snprintf(buffer, 128, "%c/%c/%c/",
+ airport[0], airport[1], airport[2]);
+ cacheData.append(buffer);
+ if (!cacheData.exists()) {
+ cacheData.create_dir(0777);
+ }
+ cacheData.append(airport + "-groundnet-cache.txt");
+ cachefile.open(cacheData.str().c_str());
+ saveData = true;
+ }
+ }
+ cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl;
for (FGTaxiNodeVectorIterator node = nodes.begin();
node != nodes.end(); node++) {
+ if (saveData) {
+ cachefile << (*node)->getIndex () << " "
+ << (*node)->getElevation () << " "
+ << endl;
+ }
delete(*node);
}
nodes.clear();
delete(*seg);
}
segments.clear();
+ if (saveData) {
+ cachefile.close();
+ }
+}
+
+void FGGroundNetwork::saveElevationCache() {
+ //cerr << "Running Groundnetwork Destructor " << endl;
+ bool saveData = false;
+ ofstream cachefile;
+ if (fgGetBool("/sim/ai/groundnet-cache")) {
+ SGPath cacheData(fgGetString("/sim/fg-home"));
+ cacheData.append("ai");
+ string airport = parent->getId();
+
+ if ((airport) != "") {
+ char buffer[128];
+ ::snprintf(buffer, 128, "%c/%c/%c/",
+ airport[0], airport[1], airport[2]);
+ cacheData.append(buffer);
+ if (!cacheData.exists()) {
+ cacheData.create_dir(0777);
+ }
+ cacheData.append(airport + "-groundnet-cache.txt");
+ cachefile.open(cacheData.str().c_str());
+ saveData = true;
+ }
+ }
+ cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl;
+ for (FGTaxiNodeVectorIterator node = nodes.begin();
+ node != nodes.end(); node++) {
+ if (saveData) {
+ cachefile << (*node)->getIndex () << " "
+ << (*node)->getElevation () << " "
+ << endl;
+ }
+ }
+ if (saveData) {
+ cachefile.close();
+ }
}
void FGGroundNetwork::addSegment(const FGTaxiSegment & seg)
void FGGroundNetwork::init()
{
+ if (networkInitialized) {
+ FGATCController::init();
+ //cerr << "FGground network already initialized" << endl;
+ return;
+ }
hasNetwork = true;
+ nextSave = 0;
int index = 1;
sort(nodes.begin(), nodes.end(), compare_nodes);
//sort(segments.begin(), segments.end(), compare_segments());
while (i != segments.end()) {
(*i)->setStart(&nodes);
(*i)->setEnd(&nodes);
- (*i)->setDimensions(parent->getElevation());
+ (*i)->setDimensions(parent->getElevation() * SG_FEET_TO_METER);
(*i)->setIndex(index);
if ((*i)->isPushBack()) {
pushBackNodes.push_back((*i)->getEnd());
//}
//cerr << "Done initializing ground network" << endl;
//exit(1);
+ if (fgGetBool("/sim/ai/groundnet-cache")) {
+ SGPath cacheData(fgGetString("/sim/fg-home"));
+ cacheData.append("ai");
+ string airport = parent->getId();
+
+ if ((airport) != "") {
+ char buffer[128];
+ ::snprintf(buffer, 128, "%c/%c/%c/",
+ airport[0], airport[1], airport[2]);
+ cacheData.append(buffer);
+ if (!cacheData.exists()) {
+ cacheData.create_dir(0777);
+ }
+ int index;
+ double elev;
+ cacheData.append(airport + "-groundnet-cache.txt");
+ if (cacheData.exists()) {
+ ifstream data(cacheData.c_str());
+ string revisionStr;
+ data >> revisionStr;
+ if (revisionStr != "[GroundNetcachedata:ref:2011:09:04]") {
+ SG_LOG(SG_GENERAL, SG_ALERT,"GroundNetwork Warning: discarding outdated cachefile " <<
+ cacheData.c_str() << " for Airport " << airport);
+ } else {
+ for (FGTaxiNodeVectorIterator i = nodes.begin();
+ i != nodes.end();
+ i++) {
+ (*i)->setElevation(parent->getElevation() * SG_FEET_TO_METER);
+ data >> index >> elev;
+ if (data.eof())
+ break;
+ if (index != (*i)->getIndex()) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "Index read from ground network cache at airport " << airport << " does not match index in the network itself");
+ } else {
+ (*i)->setElevation(elev);
+ }
+ }
+ }
+ }
+ }
+ }
+ //cerr << "Finished initializing " << parent->getId() << " groundnetwork " << endl;
+ networkInitialized = true;
}
int FGGroundNetwork::findNearestNode(const SGGeod & aGeod)
}
}
+
void FGGroundNetwork::signOff(int id)
{
TrafficVectorIterator i = activeTraffic.begin();
i = activeTraffic.erase(i);
}
}
-
+/**
+ * The ground network can deal with the following states:
+ * 0 = Normal; no action required
+ * 1 = "Acknowledge "Hold position
+ * 2 = "Acknowledge "Resume taxi".
+ * 3 = "Issue TaxiClearance"
+ * 4 = Acknowledge Taxi Clearance"
+ * 5 = Post acknowlegde taxiclearance: Start taxiing
+ * 6 = Report runway
+ * 7 = Acknowledge report runway
+ * 8 = Switch tower frequency
+ * 9 = Acknowledge switch tower frequency
+ *************************************************************************************************************************/
bool FGGroundNetwork::checkTransmissionState(int minState, int maxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
AtcMsgDir msgDir)
{
int state = i->getState();
if ((state >= minState) && (state <= maxState) && available) {
if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) {
-
- cerr << "Checking state " << state << " for " << i->getAircraft()->getCallSign() << endl;
+ //cerr << "Checking state " << state << " for " << i->getAircraft()->getCallSign() << endl;
static SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
int n = trans_num->getIntValue();
- if (n >= 0) {
+ if (n == 0) {
trans_num->setIntValue(-1);
// PopupCallback(n);
- cerr << "Selected transmission message" << n << endl;
+ //cerr << "Selected transmission message " << n << endl;
+ FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
+ atc->getATCDialog()->removeEntry(1);
} else {
- cerr << "creading message for " << i->getAircraft()->getCallSign() << endl;
+ //cerr << "creating message for " << i->getAircraft()->getCallSign() << endl;
transmit(&(*i), msgId, msgDir, false);
return false;
}
}
- //cerr << "Transmitting startup msg" << endl;
transmit(&(*i), msgId, msgDir, true);
i->updateState();
lastTransmission = now;
double heading, double speed, double alt,
double dt)
{
+ time_t currentTime = time(NULL);
+ if (nextSave < currentTime) {
+ saveElevationCache();
+ nextSave = currentTime + 100 + rand() % 200;
+ }
// Check whether aircraft are on hold due to a preceding pushback. If so, make sure to
// Transmit air-to-ground "Ready to taxi request:
// Transmit ground to air approval / hold
if ((state == 5) && available) {
current->setState(0);
current->getAircraft()->setTaxiClearanceRequest(false);
- current->setHoldPosition(true);
+ current->setHoldPosition(false);
available = false;
}
}
-
}
/**
if (bearing > 180)
bearing = 360 - bearing;
if ((dist < mindist) && (bearing < 60.0)) {
+ //cerr << "Current aircraft " << current->getAircraft()->getTrafficRef()->getCallSign()
+ // << " is closest to " << i->getAircraft()->getTrafficRef()->getCallSign()
+ // << ", which has status " << i->getAircraft()->isScheduledForTakeoff()
+ // << endl;
mindist = dist;
closest = i;
minbearing = bearing;
}
}
// Finally, check UserPosition
+ // Note, as of 2011-08-01, this should no longer be necessecary.
+ /*
double userLatitude = fgGetDouble("/position/latitude-deg");
double userLongitude = fgGetDouble("/position/longitude-deg");
SGGeod user(SGGeod::fromDeg(userLongitude, userLatitude));
minbearing = bearing;
otherReasonToSlowDown = true;
}
-
+ */
current->clearSpeedAdjustment();
if (current->checkPositionAndIntentions(*closest)
return;
else
current->setWaitsForId(closest->getId());
- if (closest->getId() != current->getId())
+ if (closest->getId() != current->getId()) {
current->setSpeedAdjustment(closest->getSpeed() *
(mindist / 100));
- else
+ if (
+ closest->getAircraft()->getTakeOffStatus() &&
+ (current->getAircraft()->getTrafficRef()->getDepartureAirport() == closest->getAircraft()->getTrafficRef()->getDepartureAirport()) &&
+ (current->getAircraft()->GetFlightPlan()->getRunway() == closest->getAircraft()->GetFlightPlan()->getRunway())
+ )
+ current->getAircraft()->scheduleForATCTowerDepartureControl(1);
+ } else {
current->setSpeedAdjustment(0); // This can only happen when the user aircraft is the one closest
+ }
if (mindist < maxAllowableDistance) {
//double newSpeed = (maxAllowableDistance-mindist);
//current->setSpeedAdjustment(newSpeed);
//(!(current->getSpeedAdjustment())))
{
- current->setHoldPosition(true);
- current->setWaitsForId(i->getId());
+ if (!(isUserAircraft(i->getAircraft()))) { // test code. Don't wait for the user, let the user wait for you.
+ current->setHoldPosition(true);
+ current->setWaitsForId(i->getId());
+ }
//cerr << "Hold check 5: " << current->getCallSign() <<" Setting Hold Position: distance to node (" << node << ") "
// << dist << " meters. Waiting for " << i->getCallSign();
//if (opposing)
}
}
bool currStatus = current->hasHoldPosition();
-
+ current->setHoldPosition(origStatus);
// Either a Hold Position or a resume taxi transmission has been issued
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
if ((now - lastTransmission) > 2) {
available = true;
}
- if ((origStatus != currStatus) && available) {
- //cerr << "Issueing hold short instrudtion " << currStatus << " " << available << endl;
- if (currStatus == true) { // No has a hold short instruction
- transmit(&(*current), MSG_HOLD_POSITION, ATC_GROUND_TO_AIR, true);
- //cerr << "Transmittin hold short instrudtion " << currStatus << " " << available << endl;
- current->setState(1);
- } else {
- transmit(&(*current), MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true);
- //cerr << "Transmittig resume instrudtion " << currStatus << " " << available << endl;
- current->setState(2);
+ if (current->getState() == 0) {
+ if ((origStatus != currStatus) && available) {
+ //cerr << "Issueing hold short instrudtion " << currStatus << " " << available << endl;
+ if (currStatus == true) { // No has a hold short instruction
+ transmit(&(*current), MSG_HOLD_POSITION, ATC_GROUND_TO_AIR, true);
+ //cerr << "Transmittin hold short instrudtion " << currStatus << " " << available << endl;
+ current->setState(1);
+ } else {
+ transmit(&(*current), MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true);
+ //cerr << "Transmittig resume instrudtion " << currStatus << " " << available << endl;
+ current->setState(2);
+ }
+ lastTransmission = now;
+ available = false;
+ // Don't act on the changed instruction until the transmission is confirmed
+ // So set back to original status
+ //cerr << "Current state " << current->getState() << endl;
}
- lastTransmission = now;
- available = false;
- // Don't act on the changed instruction until the transmission is confirmed
- // So set back to original status
- current->setHoldPosition(origStatus);
- //cerr << "Current state " << current->getState() << endl;
- } else {
+
}
+ // 6 = Report runway
+ // 7 = Acknowledge report runway
+ // 8 = Switch tower frequency
+ //9 = Acknowledge switch tower frequency
+
//int state = current->getState();
if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) {
current->setState(0);
current->setState(0);
current->setHoldPosition(false);
}
+ if (current->getAircraft()->getTakeOffStatus() && (current->getState() == 0)) {
+ //cerr << "Scheduling " << current->getAircraft()->getCallSign() << " for hold short" << endl;
+ current->setState(6);
+ }
+ if (checkTransmissionState(6,6, current, now, MSG_REPORT_RUNWAY_HOLD_SHORT, ATC_AIR_TO_GROUND)) {
+ }
+ if (checkTransmissionState(7,7, current, now, MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT, ATC_GROUND_TO_AIR)) {
+ }
+ if (checkTransmissionState(8,8, current, now, MSG_SWITCH_TOWER_FREQUENCY, ATC_GROUND_TO_AIR)) {
+ }
+ if (checkTransmissionState(9,9, current, now, MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY, ATC_AIR_TO_GROUND)) {
+ }
- /*if ((state == 1) && (available)) {
- //cerr << "ACKNOWLEDGE HOLD" << endl;
- transmit(&(*current), MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND, true);
- current->setState(0);
- current->setHoldPosition(true);
- lastTransmission = now;
- available = false;
- }
- if ((state == 2) && (available)) {
- //cerr << "ACKNOWLEDGE RESUME" << endl;
- transmit(&(*current), MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND, true);
- current->setState(0);
- current->setHoldPosition(false);
- lastTransmission = now;
- available = false;
- }*/
+
+ //current->setState(0);
}
/**
// Note that this function is copied from simgear. for maintanance purposes, it's probabtl better to make a general function out of that.
static void WorldCoordinate(osg::Matrix& obj_pos, double lat,
- double lon, double elev, double hdg)
+ double lon, double elev, double hdg, double slope)
{
SGGeod geod = SGGeod::fromDegM(lon, lat, elev);
obj_pos = geod.makeZUpFrame();
// around the Z axis
obj_pos.preMult(osg::Matrix::rotate(hdg * SGD_DEGREES_TO_RADIANS,
0.0, 0.0, 1.0));
+ obj_pos.preMult(osg::Matrix::rotate(slope * SGD_DEGREES_TO_RADIANS,
+ 0.0, 1.0, 0.0));
}
-void FGGroundNetwork::render()
+void FGGroundNetwork::render(bool visible)
{
SGMaterialLib *matlib = globals->get_matlib();
globals->get_scenery()->get_scene_graph()->removeChild(group);
//while (group->getNumChildren()) {
// cerr << "Number of children: " << group->getNumChildren() << endl;
- simgear::EffectGeode* geode = (simgear::EffectGeode*) group->getChild(0);
+ //simgear::EffectGeode* geode = (simgear::EffectGeode*) group->getChild(0);
//osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
//geode->releaseGLObjects();
//group->removeChild(geode);
//delete geode;
+ group = 0;
}
- group = new osg::Group;
-
- //for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
- double dx = 0;
- for (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
- // Handle start point
- int pos = i->getCurrentPosition() - 1;
- if (pos >= 0) {
+ if (visible) {
+ group = new osg::Group;
+ FGScenery * local_scenery = globals->get_scenery();
+ double elevation_meters = 0.0;
+ double elevation_feet = 0.0;
+ //for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
+ double dx = 0;
+ for (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+ // Handle start point
+ int pos = i->getCurrentPosition() - 1;
+ if (pos >= 0) {
- SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
- SGGeod end (SGGeod::fromDeg(segments[pos]->getEnd()->getLongitude(), segments[pos]->getEnd()->getLatitude()));
-
- double length = SGGeodesy::distanceM(start, end);
- //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
-
- double az2, heading; //, distanceM;
- SGGeodesy::inverse(start, end, heading, az2, length);
- double coveredDistance = length * 0.5;
- SGGeod center;
- SGGeodesy::direct(start, heading, coveredDistance, center, az2);
- //cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
+ SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
+ SGGeod end (SGGeod::fromDeg(segments[pos]->getEnd()->getLongitude(), segments[pos]->getEnd()->getLatitude()));
+
+ double length = SGGeodesy::distanceM(start, end);
+ //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
+
+ double az2, heading; //, distanceM;
+ SGGeodesy::inverse(start, end, heading, az2, length);
+ double coveredDistance = length * 0.5;
+ SGGeod center;
+ SGGeodesy::direct(start, heading, coveredDistance, center, az2);
+ //cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
///////////////////////////////////////////////////////////////////////////////
- // Make a helper function out of this
- osg::Matrix obj_pos;
+ // Make a helper function out of this
+ osg::Matrix obj_pos;
osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
obj_trans->setDataVariance(osg::Object::STATIC);
+ // Experimental: Calculate slope here, based on length, and the individual elevations
+ double elevationStart;
+ if (isUserAircraft((i)->getAircraft())) {
+ elevationStart = fgGetDouble("/position/ground-elev-m");
+ } else {
+ elevationStart = ((i)->getAircraft()->_getAltitude());
+ }
+ double elevationEnd = segments[pos]->getEnd()->getElevation();
+ //cerr << "Using elevation " << elevationEnd << endl;
+
+ if ((elevationEnd == 0) || (elevationEnd = parent->getElevation())) {
+ SGGeod center2 = end;
+ center2.setElevationM(SG_MAX_ELEVATION_M);
+ if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
+ elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
+ //elevation_meters += 0.5;
+ }
+ else {
+ elevationEnd = parent->getElevation();
+ }
+ segments[pos]->getEnd()->setElevation(elevationEnd);
+ }
+ double elevationMean = (elevationStart + elevationEnd) / 2.0;
+ double elevDiff = elevationEnd - elevationStart;
+
+ double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
+
+ //cerr << "1. Using mean elevation : " << elevationMean << " and " << slope << endl;
- WorldCoordinate( obj_pos, center.getLatitudeDeg(), center.getLongitudeDeg(), parent->elevation()+8+dx, -(heading) );
+ WorldCoordinate( obj_pos, center.getLatitudeDeg(), center.getLongitudeDeg(), elevationMean+ 0.5, -(heading), slope );
obj_trans->setMatrix( obj_pos );
//osg::Vec3 center(0, 0, 0)
// wire as much of the scene graph together as we can
//->addChild( obj_trans );
group->addChild( obj_trans );
- /////////////////////////////////////////////////////////////////////
- } else {
- cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
- }
- for(intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
- osg::Matrix obj_pos;
- int k = (*j)-1;
- if (k >= 0) {
- osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
- obj_trans->setDataVariance(osg::Object::STATIC);
-
- WorldCoordinate( obj_pos, segments[k]->getLatitude(), segments[k]->getLongitude(), parent->elevation()+8+dx, -(segments[k]->getHeading()) );
-
- obj_trans->setMatrix( obj_pos );
- //osg::Vec3 center(0, 0, 0)
+ /////////////////////////////////////////////////////////////////////
+ } else {
+ //cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
+ }
+ for(intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
+ osg::Matrix obj_pos;
+ int k = (*j)-1;
+ if (k >= 0) {
+ osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
+ obj_trans->setDataVariance(osg::Object::STATIC);
+
+ // Experimental: Calculate slope here, based on length, and the individual elevations
+ double elevationStart = segments[k]->getStart()->getElevation();
+ double elevationEnd = segments[k]->getEnd ()->getElevation();
+ if ((elevationStart == 0) || (elevationStart == parent->getElevation())) {
+ SGGeod center2 = segments[k]->getStart()->getGeod();
+ center2.setElevationM(SG_MAX_ELEVATION_M);
+ if (local_scenery->get_elevation_m( center2, elevationStart, NULL )) {
+ elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5;
+ //elevation_meters += 0.5;
+ }
+ else {
+ elevationStart = parent->getElevation();
+ }
+ segments[k]->getStart()->setElevation(elevationStart);
+ }
+ if ((elevationEnd == 0) || (elevationEnd == parent->getElevation())) {
+ SGGeod center2 = segments[k]->getEnd()->getGeod();
+ center2.setElevationM(SG_MAX_ELEVATION_M);
+ if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
+ elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
+ //elevation_meters += 0.5;
+ }
+ else {
+ elevationEnd = parent->getElevation();
+ }
+ segments[k]->getEnd()->setElevation(elevationEnd);
+ }
- float width = segments[k]->getLength() /2.0;
- osg::Vec3 corner(-width, 0, 0.25f);
- osg::Vec3 widthVec(2*width + 1, 0, 0);
- osg::Vec3 heightVec(0, 1, 0);
- osg::Geometry* geometry;
- geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
- simgear::EffectGeode* geode = new simgear::EffectGeode;
- geode->setName("test");
- geode->addDrawable(geometry);
- //osg::Node *custom_obj;
- SGMaterial *mat = matlib->find("UnidirectionalTaper");
- if (mat)
- geode->setEffect(mat->get_effect());
- obj_trans->addChild(geode);
- // wire as much of the scene graph together as we can
- //->addChild( obj_trans );
- group->addChild( obj_trans );
+ double elevationMean = (elevationStart + elevationEnd) / 2.0;
+ double elevDiff = elevationEnd - elevationStart;
+ double length = segments[k]->getLength();
+ double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
+
+ // cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl;
+
+
+ WorldCoordinate( obj_pos, segments[k]->getLatitude(), segments[k]->getLongitude(), elevationMean+ 0.5, -(segments[k]->getHeading()), slope );
+
+ obj_trans->setMatrix( obj_pos );
+ //osg::Vec3 center(0, 0, 0)
+
+ float width = segments[k]->getLength() /2.0;
+ osg::Vec3 corner(-width, 0, 0.25f);
+ osg::Vec3 widthVec(2*width + 1, 0, 0);
+ osg::Vec3 heightVec(0, 1, 0);
+ osg::Geometry* geometry;
+ geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
+ simgear::EffectGeode* geode = new simgear::EffectGeode;
+ geode->setName("test");
+ geode->addDrawable(geometry);
+ //osg::Node *custom_obj;
+ SGMaterial *mat = matlib->find("UnidirectionalTaper");
+ if (mat)
+ geode->setEffect(mat->get_effect());
+ obj_trans->addChild(geode);
+ // wire as much of the scene graph together as we can
+ //->addChild( obj_trans );
+ group->addChild( obj_trans );
+ }
}
+ //dx += 0.1;
}
- //dx += 0.1;
+ globals->get_scenery()->get_scene_graph()->addChild(group);
}
- globals->get_scenery()->get_scene_graph()->addChild(group);
-}
\ No newline at end of file
+}
+
+string FGGroundNetwork::getName() {
+ return string(parent->getId() + "-ground");
+}