+
+
+void FGGroundNetwork::render(bool visible)
+{
+
+ SGMaterialLib *matlib = globals->get_matlib();
+ if (group) {
+ //int nr = ;
+ 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);
+ //osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
+ //geode->releaseGLObjects();
+ //group->removeChild(geode);
+ //delete geode;
+ group = 0;
+ }
+ if (visible) {
+ group = new osg::Group;
+ FGScenery * local_scenery = globals->get_scenery();
+ // double elevation_meters = 0.0;
+// double elevation_feet = 0.0;
+ time_t now = time(NULL) + fgGetLong("/sim/time/warp");
+ //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;
+ ///////////////////////////////////////////////////////////////////////////////
+ // 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()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
+ //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(), elevationMean+ 0.5, -(heading), slope );
+
+ obj_trans->setMatrix( obj_pos );
+ //osg::Vec3 center(0, 0, 0)
+
+ float width = length /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;
+ if (segments[pos]->hasBlock(now)) {
+ mat = matlib->find("UnidirectionalTaperRed");
+ } else {
+ mat = matlib->find("UnidirectionalTaperGreen");
+ }
+ 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 );
+ /////////////////////////////////////////////////////////////////////
+ } 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()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
+ double elevationEnd = segments[k]->getEnd ()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
+ 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);
+ }
+
+ 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;
+ if (segments[k]->hasBlock(now)) {
+ mat = matlib->find("UnidirectionalTaperRed");
+ } else {
+ mat = matlib->find("UnidirectionalTaperGreen");
+ }
+ 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;
+ }
+ globals->get_scenery()->get_scene_graph()->addChild(group);
+ }
+}
+
+string FGGroundNetwork::getName() {
+ return string(parent->getId() + "-ground");
+}
+
+void FGGroundNetwork::update(double dt)
+{
+ time_t now = time(NULL) + fgGetLong("/sim/time/warp");
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ (*tsi)->unblock(now);
+ }
+ int priority = 1;
+ //sort(activeTraffic.begin(), activeTraffic.end(), compare_trafficrecords);
+ // Handle traffic that is under ground control first; this way we'll prevent clutter at the gate areas.
+ // Don't allow an aircraft to pushback when a taxiing aircraft is currently using part of the intended route.
+ for (TrafficVectorIterator i = parent->getDynamics()->getStartupController()->getActiveTraffic().begin();
+ i != parent->getDynamics()->getStartupController()->getActiveTraffic().end(); i++) {
+ i->allowPushBack();
+ i->setPriority(priority++);
+ // in meters per second;
+ double vTaxi = (i->getAircraft()->getPerformance()->vTaxi() * SG_NM_TO_METER) / 3600;
+ if (i->isActive(0)) {
+
+ // Check for all active aircraft whether it's current pos segment is
+ // an opposite of one of the departing aircraft's intentions
+ for (TrafficVectorIterator j = activeTraffic.begin(); j != activeTraffic.end(); j++) {
+ int pos = j->getCurrentPosition();
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1]->opposite();
+ if (seg) {
+ int posReverse = seg->getIndex();
+ for (intVecIterator k = i->getIntentions().begin(); k != i->getIntentions().end(); k++) {
+ if ((*k) == posReverse) {
+ i->denyPushBack();
+ segments[posReverse-1]->block(i->getId(), now, now);
+ }
+ }
+ }
+ }
+ }
+ // if the current aircraft is still allowed to pushback, we can start reserving a route for if by blocking all the entry taxiways.
+ if (i->pushBackAllowed()) {
+ double length = 0;
+ int pos = i->getCurrentPosition();
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1];
+ FGTaxiNode *node = seg->getEnd();
+ length = seg->getLength();
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
+ (*tsi)->block(i->getId(), now, now);
+ }
+ }
+ }
+ for (intVecIterator j = i->getIntentions().begin(); j != i->getIntentions().end(); j++) {
+ int pos = (*j);
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1];
+ FGTaxiNode *node = seg->getEnd();
+ length += seg->getLength();
+ time_t blockTime = now + (length / vTaxi);
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
+ (*tsi)->block(i->getId(), blockTime-30, now);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ for (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+ double length = 0;
+ double vTaxi = (i->getAircraft()->getPerformance()->vTaxi() * SG_NM_TO_METER) / 3600;
+ i->setPriority(priority++);
+ int pos = i->getCurrentPosition();
+ if (pos > 0) {
+ length = segments[pos-1]->getLength();
+ if (segments[pos-1]->hasBlock(now)) {
+ //SG_LOG(SG_GENERAL, SG_ALERT, "Taxiway incursion for AI aircraft" << i->getAircraft()->getCallSign());
+ }
+
+ }
+ intVecIterator ivi;
+ for (ivi = i->getIntentions().begin(); ivi != i->getIntentions().end(); ivi++) {
+ int segIndex = (*ivi);
+ if (segIndex > 0) {
+ if (segments[segIndex-1]->hasBlock(now))
+ break;
+ }
+ }
+ //after this, ivi points just behind the last valid unblocked taxi segment.
+ for (intVecIterator j = i->getIntentions().begin(); j != ivi; j++) {
+ int pos = (*j);
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1];
+ FGTaxiNode *node = seg->getEnd();
+ length += seg->getLength();
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
+ time_t blockTime = now + (length / vTaxi);
+ (*tsi)->block(i->getId(), blockTime - 30, now);
+ }
+ }
+ }
+ }
+ }
+}
+