In preparation for caching the groundnet in the NavCache, make taxi-nodes and parkings inherit from FGPositioned. As part of this, make them heap (as opposed to value) classes, disable their copy-constructors, remove many mutating operations, and give them real constructors.
FGTaxiNode *tn =
apt->getDynamics()->getGroundNetwork()->findNode(node);
FGAIWaypoint *wpt =
- createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(),
+ createOnGround(ac, buffer, tn->geod(), apt->getElevation(),
ac->getPerformance()->vTaxi());
wpt->setRouteIndex(route);
//cerr << "Nodes left " << taxiRoute->nodesLeft() << " ";
FGParking* parkPos = aAirport->getDynamics()->getParking(gateId);
if (parkPos) {
- wpt = createOnGround(ac, "ENDtaxi", parkPos->getGeod(), airportElev,
+ wpt = createOnGround(ac, "ENDtaxi", parkPos->geod(), airportElev,
ac->getPerformance()->vTaxi());
pushBackWaypoint(wpt);
}
snprintf(buffer, 10, "%d", node);
FGTaxiNode *tn = gn->findNode(node);
FGAIWaypoint *wpt =
- createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(),
+ createOnGround(ac, buffer, tn->geod(), apt->getElevation(),
ac->getPerformance()->vTaxi());
wpt->setRouteIndex(route);
pushBackWaypoint(wpt);
if (!tn)
break;
- double dist = SGGeodesy::distanceM(coord, tn->getGeod());
+ double dist = SGGeodesy::distanceM(coord, tn->geod());
if (dist < (min + 0.75)) {
break;
}
min = dist;
}
if (tn) {
- wpt = createOnGround(ac, buffer, tn->getGeod(), currElev, vTaxi);
+ wpt = createOnGround(ac, buffer, tn->geod(), currElev, vTaxi);
pushBackWaypoint(wpt);
}
}
double az; // unused
SGGeod pos;
- SGGeodesy::direct(parking->getGeod(), heading, 2.2 * parking->getRadius(),
+ SGGeodesy::direct(parking->geod(), heading, 2.2 * parking->getRadius(),
pos, az);
wpt = createOnGround(ac, "taxiStart", pos, aptElev, vTaxiReduced);
pushBackWaypoint(wpt);
- SGGeodesy::direct(parking->getGeod(), heading, 0.1 * parking->getRadius(),
+ SGGeodesy::direct(parking->geod(), heading, 0.1 * parking->getRadius(),
pos, az);
wpt = createOnGround(ac, "taxiStart2", pos, aptElev, vTaxiReduced);
pushBackWaypoint(wpt);
- wpt = createOnGround(ac, "END-Parking", parking->getGeod(), aptElev,
+ wpt = createOnGround(ac, "END-Parking", parking->geod(), aptElev,
vTaxiReduced);
pushBackWaypoint(wpt);
return true;
FGTaxiRoute route;
//cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl;
route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false);
- parking->setPushBackRoute(new FGTaxiRoute(route));
-
+ parking->setPushBackRoute(std::auto_ptr<FGTaxiRoute>(new FGTaxiRoute(route)));
pushBackRoute = parking->getPushBackRoute();
int size = pushBackRoute->size();
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
//ids.pop_back();
//wpt = new waypoint;
- FGAIWaypoint *wpt = createOnGround(ac, string(buffer), tn->getGeod(), dep->getElevation(), vTaxiBackward);
+ FGAIWaypoint *wpt = createOnGround(ac, string(buffer), tn->geod(), dep->getElevation(), vTaxiBackward);
wpt->setRouteIndex(rte);
pushBackWaypoint(wpt);
//cerr << "Creating final push forward point for gate " << gateId << endl;
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId);
- FGTaxiSegmentVectorIterator ts = tn->getBeginRoute();
- FGTaxiSegmentVectorIterator te = tn->getEndRoute();
- // if the starting node equals the ending node, then there aren't any routes for this parking.
+ // there aren't any routes for this parking.
// in cases like these we should flag the gate as being inoperative and return false
- if (ts == te) {
+ if (tn->arcs().empty()) {
SG_LOG(SG_AI, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it.");
parking->setAvailable(false);
return false;
}
- tn = (*ts)->getEnd();
- lastNodeVisited = tn->getIndex();
- if (tn == NULL) {
- SG_LOG(SG_AI, SG_ALERT, "No valid taxinode found");
- exit(1);
- }
- double distance = (*ts)->getLength();
+
+ FGTaxiSegment* pushForwardSegment = tn->arcs().front();
+ lastNodeVisited = pushForwardSegment->getEnd()->getIndex();
+ double distance = pushForwardSegment->getLength();
double parkingHeading = parking->getHeading();
for (int i = 1; i < 10; i++) {
SGGeod pushForwardPt;
- SGGeodesy::direct(parking->getGeod(), parkingHeading,
+ SGGeodesy::direct(parking->geod(), parkingHeading,
((i / 10.0) * distance), pushForwardPt, az2);
char buffer[16];
snprintf(buffer, 16, "pushback-%02d", i);
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), pushForwardPt, dep->getElevation(), vTaxiReduced);
- wpt->setRouteIndex((*ts)->getIndex());
+ wpt->setRouteIndex(pushForwardSegment->getIndex());
pushBackWaypoint(wpt);
}
// cerr << "Done " << endl;
if (pos > 0) {
FGTaxiSegment *segment = parent->getGroundNetwork()->findSegment(pos);
SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
- SGGeod end (SGGeod::fromDeg(segment->getEnd()->getLongitude(), segment->getEnd()->getLatitude()));
+ SGGeod end (segment->getEnd()->geod());
double length = SGGeodesy::distanceM(start, end);
- //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
+ //heading = SGGeodesy::headingDeg(start->geod(), end->geod());
double az2, heading; //, distanceM;
SGGeodesy::inverse(start, end, heading, az2, length);
double elevationStart = segment->getStart()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
double elevationEnd = segment->getEnd ()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
if ((elevationStart == 0) || (elevationStart == parent->getElevation())) {
- SGGeod center2 = segment->getStart()->getGeod();
+ SGGeod center2 = segment->getStart()->geod();
center2.setElevationM(SG_MAX_ELEVATION_M);
if (local_scenery->get_elevation_m( center2, elevationStart, NULL )) {
//elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5;
segment->getStart()->setElevation(elevationStart);
}
if ((elevationEnd == 0) || (elevationEnd == parent->getElevation())) {
- SGGeod center2 = segment->getEnd()->getGeod();
+ SGGeod center2 = segment->getEnd()->geod();
center2.setElevationM(SG_MAX_ELEVATION_M);
if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
//elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
//cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl;
-
- WorldCoordinate( obj_pos, segment->getLatitude(), segment->getLongitude(), elevationMean + 0.5 + dx, -(segment->getHeading()), slope );
+ SGGeod segCenter(segment->getCenter());
+ WorldCoordinate( obj_pos, segCenter.getLatitudeDeg(),
+ segCenter.getLongitudeDeg(), elevationMean + 0.5 + dx, -(segment->getHeading()), slope );
//WorldCoordinate( obj_pos, segment->getLatitude(), segment->getLongitude(), parent->getElevation()+8+dx, -(segment->getHeading()) );
#include "dynamicloader.hxx"
+/*****************************************************************************
+ * Helper function for parsing position string
+ ****************************************************************************/
+static double processPosition(const string &pos)
+{
+ string prefix;
+ string subs;
+ string degree;
+ string decimal;
+ int sign = 1;
+ double value;
+ subs = pos;
+ prefix= subs.substr(0,1);
+ if (prefix == string("S") || (prefix == string("W")))
+ sign = -1;
+ subs = subs.substr(1, subs.length());
+ degree = subs.substr(0, subs.find(" ",0));
+ decimal = subs.substr(subs.find(" ",0), subs.length());
+
+ value = sign * (atof(degree.c_str()) + atof(decimal.c_str())/60.0);
+ return value;
+}
+
FGAirportDynamicsXMLLoader::FGAirportDynamicsXMLLoader(FGAirportDynamics* dyn):
- XMLVisitor(), _dynamics(dyn) {}
+ XMLVisitor(), _dynamics(dyn)
+{}
void FGAirportDynamicsXMLLoader::startXML () {
//cout << "FGAirportDynamicsLoader::Start XML" << endl;
//cout << "End XML" << endl;
}
-void FGAirportDynamicsXMLLoader::startElement (const char * name, const XMLAttributes &atts) {
- // const char *attval;
- FGParking park;
- FGTaxiNode taxiNode;
- FGTaxiSegment taxiSegment;
- int index = 0;
- string idxStr;
- taxiSegment.setIndex(index);
- //cout << "Start element " << name << endl;
- string attname;
- string value;
- string gateName;
- string gateNumber;
- string attval;
- string lat;
- string lon;
- int holdPointType;
- int pushBackPoint;
+void FGAirportDynamicsXMLLoader::startParking(const XMLAttributes &atts)
+{
+ string type;
+ int index;
+ string gateName, gateNumber;
+ string lat, lon;
+ double heading = 0.0;
+ double radius = 1.0;
+ string airlineCodes;
+ int pushBackRoute = 0;
- if (name == string("Parking"))
- {
- pushBackPoint = 0;
- for (int i = 0; i < atts.size(); i++)
+ for (int i = 0; i < atts.size(); i++)
{
- //cout << " " << atts.getName(i) << '=' << atts.getValue(i) << endl;
- attname = atts.getName(i);
- if (attname == string("index")) {
- park.setIndex(std::atoi(atts.getValue(i)));
- idxStr = atts.getValue(i);
- }
- else if (attname == string("type"))
- park.setType(atts.getValue(i));
- else if (attname == string("name"))
- gateName = atts.getValue(i);
- else if (attname == string("number"))
+ string attname(atts.getName(i));
+ if (attname == "index") {
+ index = std::atoi(atts.getValue(i));
+ } else if (attname == "type")
+ type = atts.getValue(i);
+ else if (attname == "name")
+ gateName = atts.getValue(i);
+ else if (attname == "number")
gateNumber = atts.getValue(i);
- else if (attname == string("lat"))
- park.setLatitude(atts.getValue(i));
- else if (attname == string("lon"))
- park.setLongitude(atts.getValue(i));
- else if (attname == string("heading"))
- park.setHeading(std::atof(atts.getValue(i)));
- else if (attname == string("radius")) {
- string radius = atts.getValue(i);
- if (radius.find("M") != string::npos)
- radius = radius.substr(0, radius.find("M",0));
- //cerr << "Radius " << radius <<endl;
- park.setRadius(std::atof(radius.c_str()));
+ else if (attname == "lat")
+ lat = atts.getValue(i);
+ else if (attname == "lon")
+ lon = atts.getValue(i);
+ else if (attname == "heading")
+ heading = std::atof(atts.getValue(i));
+ else if (attname == "radius") {
+ string radiusStr = atts.getValue(i);
+ if (radiusStr.find("M") != string::npos)
+ radiusStr = radiusStr.substr(0, radiusStr.find("M",0));
+ radius = std::atof(radiusStr.c_str());
}
- else if (attname == string("airlineCodes"))
- park.setCodes(atts.getValue(i));
- else if (attname == string("pushBackRoute")) {
- pushBackPoint = std::atoi(atts.getValue(i));
- //park.setPushBackPoint(std::atoi(atts.getValue(i)));
-
- }
- }
- park.setPushBackPoint(pushBackPoint);
- park.setName((gateName+gateNumber));
- //cerr << "Parking " << idxStr << "( " << gateName << gateNumber << ") has pushBackPoint " << pushBackPoint << endl;
- _dynamics->addParking(park);
+ else if (attname == "airlineCodes")
+ airlineCodes = atts.getValue(i);
+ else if (attname == "pushBackRoute") {
+ pushBackRoute = std::atoi(atts.getValue(i));
}
- if (name == string("node"))
- {
- for (int i = 0; i < atts.size() ; i++)
- {
- attname = atts.getName(i);
- if (attname == string("index"))
- taxiNode.setIndex(std::atoi(atts.getValue(i)));
- if (attname == string("lat"))
- taxiNode.setLatitude(atts.getValue(i));
- if (attname == string("lon"))
- taxiNode.setLongitude(atts.getValue(i));
- if (attname == string("isOnRunway"))
- taxiNode.setOnRunway((bool) std::atoi(atts.getValue(i)));
- if (attname == string("holdPointType")) {
- attval = atts.getValue(i);
- if (attval==string("none")) {
- holdPointType=0;
- } else if (attval==string("normal")) {
- holdPointType=1;
- } else if (attval==string("CAT II/III")) {
- holdPointType=3;
- } else if (attval==string("PushBack")) {
- holdPointType=3;
- } else {
- holdPointType=0;
- }
- //cerr << "Setting Holding point to " << holdPointType << endl;
- taxiNode.setHoldPointType(holdPointType);
- }
}
- _dynamics->getGroundNetwork()->addNode(taxiNode);
+
+ SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat)));
+
+ FGParking* pk = new FGParking(0, index, pos, heading, radius,
+ gateName + gateNumber, type, airlineCodes);
+ pk->setPushBackPoint(pushBackRoute);
+ _dynamics->addParking(pk);
+}
+
+void FGAirportDynamicsXMLLoader::startNode(const XMLAttributes &atts)
+{
+ int index;
+ string lat, lon;
+ bool onRunway;
+ int holdPointType;
+
+ for (int i = 0; i < atts.size() ; i++)
+ {
+ string attname(atts.getName(i));
+ if (attname == "index")
+ index = std::atoi(atts.getValue(i));
+ else if (attname == "lat")
+ lat = atts.getValue(i);
+ else if (attname == "lon")
+ lon = atts.getValue(i);
+ else if (attname == "isOnRunway")
+ onRunway = (bool) std::atoi(atts.getValue(i));
+ else if (attname == "holdPointType") {
+ string attval = atts.getValue(i);
+ if (attval=="none") {
+ holdPointType=0;
+ } else if (attval=="normal") {
+ holdPointType=1;
+ } else if (attval=="CAT II/III") {
+ holdPointType=3;
+ } else if (attval=="PushBack") {
+ holdPointType=3;
+ } else {
+ holdPointType=0;
+ }
}
- if (name == string("arc"))
- {
- taxiSegment.setIndex(++index);
- for (int i = 0; i < atts.size() ; i++)
+ }
+
+ SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat)));
+ FGTaxiNode* taxiNode = new FGTaxiNode(0, index, pos, onRunway, holdPointType);
+ _dynamics->getGroundNetwork()->addNode(taxiNode);
+}
+
+void FGAirportDynamicsXMLLoader::startArc(const XMLAttributes &atts)
+{
+ int begin, end;
+ bool isPushBackRoute = false;
+
+ for (int i = 0; i < atts.size() ; i++)
{
- attname = atts.getName(i);
- if (attname == string("begin"))
- taxiSegment.setStartNodeRef(std::atoi(atts.getValue(i)));
- if (attname == string("end"))
- taxiSegment.setEndNodeRef(std::atoi(atts.getValue(i)));
- if (attname == string("isPushBackRoute"))
- taxiSegment.setPushBackType((bool) std::atoi(atts.getValue(i)));
+ string attname = atts.getName(i);
+ if (attname == "begin")
+ begin = std::atoi(atts.getValue(i));
+ else if (attname == "end")
+ end = std::atoi(atts.getValue(i));
+ else if (attname == "isPushBackRoute")
+ isPushBackRoute = (bool) std::atoi(atts.getValue(i));
}
- _dynamics->getGroundNetwork()->addSegment(taxiSegment);
- }
- // sort by radius, in asending order, so that smaller gates are first in the list
+
+ _dynamics->getGroundNetwork()->addSegment(new FGTaxiSegment(begin, end, isPushBackRoute));
}
-void FGAirportDynamicsXMLLoader::endElement (const char * name) {
- //cout << "End element " << name << endl;
- if (name == string("version")) {
- _dynamics->getGroundNetwork()->addVersion(atoi(value.c_str()));
- //std::cerr << "version" << value<< std::endl;
- }
- if (name == string("AWOS")) {
- _dynamics->addAwosFreq(atoi(value.c_str()));
- //cerr << "Adding AWOS" << value<< endl;
- }
- if (name == string("UNICOM")) {
- _dynamics->addUnicomFreq(atoi(value.c_str()));
- //cerr << "UNICOM" << value<< endl;
- }
-if (name == string("CLEARANCE")) {
- _dynamics->addClearanceFreq(atoi(value.c_str()));
- //cerr << "Adding CLEARANCE" << value<< endl;
- }
-if (name == string("GROUND")) {
- _dynamics->addGroundFreq(atoi(value.c_str()));
- //cerr << "Adding GROUND" << value<< endl;
+void FGAirportDynamicsXMLLoader::startElement (const char * name, const XMLAttributes &atts)
+{
+ if (!strcmp("Parking", name)) {
+ startParking(atts);
+ } else if (!strcmp("node", name)) {
+ startNode(atts);
+ } else if (!strcmp("arc", name)) {
+ startArc(atts);
}
+}
-if (name == string("TOWER")) {
- _dynamics->addTowerFreq(atoi(value.c_str()));
- //cerr << "Adding TOWER" << value<< endl;
- }
-if (name == string("APPROACH")) {
- _dynamics->addApproachFreq(atoi(value.c_str()));
- //cerr << "Adding approach" << value<< endl;
+void FGAirportDynamicsXMLLoader::endElement (const char * name)
+{
+ int valueAsInt = atoi(value.c_str());
+ if (!strcmp("version", name)) {
+ _dynamics->getGroundNetwork()->addVersion(valueAsInt);
+ } else if (!strcmp("AWOS", name)) {
+ _dynamics->addAwosFreq(valueAsInt);
+ } else if (!strcmp("UNICOM", name)) {
+ _dynamics->addUnicomFreq(valueAsInt);
+ } else if (!strcmp("CLEARANCE", name)) {
+ _dynamics->addClearanceFreq(valueAsInt);
+ } else if (!strcmp("GROUND", name)) {
+ _dynamics->addGroundFreq(valueAsInt);
+ } else if (!strcmp("TOWER", name)) {
+ _dynamics->addTowerFreq(valueAsInt);
+ } else if (!strcmp("APPROACH", name)) {
+ _dynamics->addApproachFreq(valueAsInt);
}
-
}
void FGAirportDynamicsXMLLoader::data (const char * s, int len) {
virtual void error (const char * message, int line, int column);
private:
+ void startParking(const XMLAttributes &atts);
+ void startNode(const XMLAttributes &atts);
+ void startArc(const XMLAttributes &atts);
+
FGAirportDynamics* _dynamics;
string value;
};
const string & airline,
bool skipEmptyAirlineCode)
{
- FGParkingVecIterator i;
- for (i = parkings.begin(); i != parkings.end(); i++) {
+ BOOST_FOREACH(FGParking* i, parkings) {
// Taken by another aircraft, or no airline codes
if (!i->isAvailable()) {
continue;
FGParking *FGAirportDynamics::getParking(int id)
{
- FGParkingVecIterator i = parkings.begin();
- for (i = parkings.begin(); i != parkings.end(); i++) {
- if (id == i->getIndex()) {
- return &(*i);
- }
+ BOOST_FOREACH(FGParking* i, parkings) {
+ if (id == i->getIndex()) {
+ return i;
}
- return 0;
+ }
+
+ return NULL;
}
string FGAirportDynamics::getParkingName(int id)
{
- FGParkingVecIterator i = parkings.begin();
- for (i = parkings.begin(); i != parkings.end(); i++) {
- if (id == i->getIndex()) {
- return i->getName();
- }
- }
-
- return string("overflow");
+ FGParking* p = getParking(id);
+ if (p) {
+ return p->getName();
+ }
+
+ return string();
}
int FGAirportDynamics::findParkingByName(const std::string& name) const
{
- FGParkingVec::const_iterator i = parkings.begin();
- for (i = parkings.begin(); i != parkings.end(); i++) {
- if (i->getName() == name) {
+ BOOST_FOREACH(FGParking* i, parkings) {
+ if (name == i->getName()) {
return i->getIndex();
}
}
-
+
return -1;
}
void FGAirportDynamics::releaseParking(int id)
{
if (id >= 0) {
-
- FGParkingVecIterator i = parkings.begin();
- for (i = parkings.begin(); i != parkings.end(); i++) {
- if (id == i->getIndex()) {
- i->setAvailable(true);
- }
- }
+ FGParking* parking = getParking(id);
+ if (parking) {
+ parking->setAvailable(true);
+ }
}
}
return rwy->ident();
}
-void FGAirportDynamics::addParking(FGParking & park)
+void FGAirportDynamics::addParking(FGParking* park)
{
parkings.push_back(park);
}
void getActiveRunway(const string& trafficType, int action, string& runway, double heading);
- void addParking(FGParking& park);
+ void addParking(FGParking* park);
/**
* retrieve an available parking by GateID, or -1 if no suitable
#include "gnnode.hxx"
-#include "groundnetwork.hxx"
-#include <iostream>
-#include <algorithm>
+#include <boost/foreach.hpp>
+
+#include "groundnetwork.hxx"
-#include <osg/Geode>
#include <Main/globals.hxx>
#include <Scenery/scenery.hxx>
-using std::sort;
-using std::string;
-
-/*****************************************************************************
- * Helper function for parsing position string
- ****************************************************************************/
-double processPosition(const string &pos)
-{
- string prefix;
- string subs;
- string degree;
- string decimal;
- int sign = 1;
- double value;
- subs = pos;
- prefix= subs.substr(0,1);
- if (prefix == string("S") || (prefix == string("W")))
- sign = -1;
- subs = subs.substr(1, subs.length());
- degree = subs.substr(0, subs.find(" ",0));
- decimal = subs.substr(subs.find(" ",0), subs.length());
-
-
- //cerr << sign << " "<< degree << " " << decimal << endl;
- value = sign * (atof(degree.c_str()) + atof(decimal.c_str())/60.0);
- //cerr << value <<endl;
- //exit(1);
- return value;
-}
-
-//bool sortByHeadingDiff(FGTaxiSegment *a, FGTaxiSegment *b) {
-// return a->hasSmallerHeadingDiff(*b);
-//}
-
-bool sortByLength(FGTaxiSegment *a, FGTaxiSegment *b) {
- return a->getLength() > b->getLength();
-}
-
/**************************************************************************
* FGTaxiNode
*************************************************************************/
-void FGTaxiNode::setElevation(double val)
-{
- geod.setElevationM(val);
-}
-void FGTaxiNode::setLatitude (double val)
+FGTaxiNode::FGTaxiNode(PositionedID aGuid, int index, const SGGeod& pos, bool aOnRunway, int aHoldType) :
+ FGPositioned(aGuid, FGPositioned::PARKING, "", pos),
+ index(index),
+ isOnRunway(aOnRunway),
+ holdType(aHoldType)
{
- geod.setLatitudeDeg(val);
+
}
-void FGTaxiNode::setLongitude(double val)
+FGTaxiNode::~FGTaxiNode()
{
- geod.setLongitudeDeg(val);
}
-void FGTaxiNode::setLatitude (const string& val)
+void FGTaxiNode::setElevation(double val)
{
- geod.setLatitudeDeg(processPosition(val));
+ // ignored for the moment
}
-void FGTaxiNode::setLongitude(const string& val)
-{
- geod.setLongitudeDeg(processPosition(val));
-}
-
double FGTaxiNode::getElevationFt(double refelev)
{
- double elevF = geod.getElevationFt();
+ double elevF = elevation();
+#if 0
double elevationEnd = 0;
if ((elevF == 0) || (elevF == refelev)) {
- SGGeod center2 = geod;
+ SGGeod center2 = mPosition;
FGScenery * local_scenery = globals->get_scenery();
center2.setElevationM(SG_MAX_ELEVATION_M);
if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
geod.setElevationM(elevationEnd);
}
}
- //cerr << "Returning elevation : " << geod.getElevationM() << ". Ref elev (feet) = " << refelev << endl;
- return geod.getElevationFt();
+#endif
+ return mPosition.getElevationFt();
}
double FGTaxiNode::getElevationM(double refelev)
{
- //double refelevFt = refelev * SG_METER_TO_FEET;
- //double retval = getElevationFt(refelevFt);
- //cerr << "Returning elevation : " << geod.getElevationM() << ". Ref elev (meters) = " << refelev << endl;
- return geod.getElevationM();
+ return geod().getElevationM();
+}
+
+FGTaxiSegment* FGTaxiNode::getArcTo(FGTaxiNode* aEnd) const
+{
+ BOOST_FOREACH(FGTaxiSegment* arc, next) {
+ if (arc->getEnd() == aEnd) {
+ return arc;
+ }
+ }
+
+ return NULL;
}
#include <string>
#include <simgear/compiler.h>
-#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+
+#include <Navaids/positioned.hxx>
class FGTaxiSegment;
+
typedef std::vector<FGTaxiSegment*> FGTaxiSegmentVector;
typedef FGTaxiSegmentVector::iterator FGTaxiSegmentVectorIterator;
bool sortByHeadingDiff(FGTaxiSegment *a, FGTaxiSegment *b);
bool sortByLength (FGTaxiSegment *a, FGTaxiSegment *b);
-class FGTaxiNode
+class FGTaxiNode : public FGPositioned
{
protected:
- SGGeod geod;
int index;
bool isOnRunway;
int holdType;
FGTaxiSegmentVector next; // a vector of pointers to all the segments leaving from this node
- // used in way finding
+ // used in way finding - should really move to a dynamic struct
double pathScore;
FGTaxiNode* previousNode;
FGTaxiSegment* previousSeg;
-public:
- FGTaxiNode() :
- index(0),
- isOnRunway(false),
- holdType(0),
- pathScore(0),
- previousNode(0),
- previousSeg(0)
-{
-};
-
- FGTaxiNode(const FGTaxiNode &other) :
- geod(other.geod),
- index(other.index),
- isOnRunway(other.isOnRunway),
- holdType(other.holdType),
- next(other.next),
- pathScore(other.pathScore),
- previousNode(other.previousNode),
- previousSeg(other.previousSeg)
-{
-};
-
-FGTaxiNode &operator =(const FGTaxiNode &other)
-{
- geod = other.geod;
- index = other.index;
- isOnRunway = other.isOnRunway;
- holdType = other.holdType;
- next = other.next;
- pathScore = other.pathScore;
- previousNode = other.previousNode;
- previousSeg = other.previousSeg;
- return *this;
-};
-
- void setIndex(int idx) { index = idx; };
- void setLatitude (double val);
- void setLongitude(double val);
+public:
+ FGTaxiNode(PositionedID aGuid, int index, const SGGeod& pos, bool aOnRunway, int aHoldType);
+ virtual ~FGTaxiNode();
+
void setElevation(double val);
- void setLatitude (const std::string& val);
- void setLongitude(const std::string& val);
void addSegment(FGTaxiSegment *segment) { next.push_back(segment); };
- void setHoldPointType(int val) { holdType = val; };
- void setOnRunway(bool val) { isOnRunway = val; };
void setPathScore (double val) { pathScore = val; };
void setPreviousNode(FGTaxiNode *val) { previousNode = val; };
FGTaxiSegment *getPreviousSegment() { return previousSeg; };
double getPathScore() { return pathScore; };
- double getLatitude() { return geod.getLatitudeDeg();};
- double getLongitude(){ return geod.getLongitudeDeg();};
- double getElevationM (double refelev=0);
- double getElevationFt(double refelev=0);
-
- const SGGeod& getGeod() const { return geod; }
+ double getElevationM (double refelev);
+ double getElevationFt(double refelev);
+
int getIndex() const { return index; };
int getHoldPointType() const { return holdType; };
bool getIsOnRunway() const { return isOnRunway; };
- FGTaxiNode *getAddress() { return this;};
- FGTaxiSegmentVectorIterator getBeginRoute() { return next.begin(); };
- FGTaxiSegmentVectorIterator getEndRoute() { return next.end(); };
+ const FGTaxiSegmentVector& arcs() const
+ { return next; }
+
+ /// find the arg which leads from this node to another.
+ /// returns NULL if no such arc exists.
+ FGTaxiSegment* getArcTo(FGTaxiNode* aEnd) const;
+
bool operator<(const FGTaxiNode &other) const { return index < other.index; };
};
-typedef std::vector<FGTaxiNode*> FGTaxiNodeVector;
+typedef SGSharedPtr<FGTaxiNode> FGTaxiNode_ptr;
+typedef std::vector<FGTaxiNode_ptr> FGTaxiNodeVector;
typedef FGTaxiNodeVector::iterator FGTaxiNodeVectorIterator;
#endif
#include <math.h>
#include <algorithm>
#include <fstream>
-
+#include <boost/foreach.hpp>
#include <osg/Geode>
#include <osg/Geometry>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/util/OsgMath.hxx>
+#include <simgear/structure/exception.hxx>
#include <Airports/simple.hxx>
#include <Airports/dynamics.hxx>
* FGTaxiSegment
**************************************************************************/
-void FGTaxiSegment::setStart(FGTaxiNodeVector * nodes)
+FGTaxiSegment::FGTaxiSegment(int aStart, int aEnd, bool isPushBack) :
+ startNode(aStart),
+ endNode(aEnd),
+ length(0),
+ heading(0),
+ isActive(0),
+ isPushBackRoute(isPushBack),
+ start(0),
+ end(0),
+ index(0),
+ oppositeDirection(0)
{
- FGTaxiNodeVectorIterator i = nodes->begin();
- while (i != nodes->end()) {
- //cerr << "Scanning start node index" << (*i)->getIndex() << endl;
- if ((*i)->getIndex() == startNode) {
- start = (*i)->getAddress();
- (*i)->addSegment(this);
- return;
- }
- i++;
- }
- SG_LOG(SG_GENERAL, SG_ALERT,
- "Could not find start node " << startNode << endl);
-}
+};
-void FGTaxiSegment::setEnd(FGTaxiNodeVector * nodes)
+bool FGTaxiSegment::bindToNodes(const IndexTaxiNodeMap& nodes)
{
- FGTaxiNodeVectorIterator i = nodes->begin();
- while (i != nodes->end()) {
- //cerr << "Scanning end node index" << (*i)->getIndex() << endl;
- if ((*i)->getIndex() == endNode) {
- end = (*i)->getAddress();
- return;
- }
- i++;
- }
- SG_LOG(SG_GENERAL, SG_ALERT,
- "Could not find end node " << endNode << endl);
+ IndexTaxiNodeMap::const_iterator it = nodes.find(startNode);
+ if (it == nodes.end()) {
+ return false;
+ }
+
+ start = it->second;
+
+ it = nodes.find(endNode);
+ if (it == nodes.end()) {
+ return false;
+ }
+
+ end = it->second;
+
+ start->addSegment(this);
+ double az2;
+ SGGeodesy::inverse(start->geod(), end->geod(), heading, az2, length);
+ return true;
}
-
-
-// There is probably a computationally cheaper way of
-// doing this.
-void FGTaxiSegment::setDimensions(double elevation)
+SGGeod FGTaxiSegment::getCenter() const
{
- length = SGGeodesy::distanceM(start->getGeod(), end->getGeod());
- //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
-
- double az2; //, distanceM;
- 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 SGGeodesy::direct(start->geod(), heading, length * 0.5);
}
-
-//void FGTaxiSegment::setCourseDiff(double crse)
-//{
-// headingDiff = fabs(course - crse);
-
-// if (headingDiff > 180)
-// headingDiff = fabs(headingDiff - 360);
-//}
-
void FGTaxiSegment::block(int id, time_t blockTime, time_t now)
{
BlockListIterator i = blockTimes.begin();
SG_LOG(SG_GENERAL, SG_ALERT,
"ALERT: Misconfigured TaxiRoute : " << nodes.
size() << " " << routes.size());
- exit(1);
+ throw sg_range_exception("misconfigured taxi route");
}
if (currNode == nodes.end())
return false;
/***************************************************************************
* FGGroundNetwork()
**************************************************************************/
-bool compare_nodes(FGTaxiNode * a, FGTaxiNode * b)
-{
- return (*a) < (*b);
-}
-
-bool compare_segments(FGTaxiSegment * a, FGTaxiSegment * b)
-{
- return (*a) < (*b);
-}
bool compare_trafficrecords(FGTrafficRecord a, FGTrafficRecord b)
{
}
}
cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl;
- for (FGTaxiNodeVectorIterator node = nodes.begin();
+ for (IndexTaxiNodeMap::iterator node = nodes.begin();
node != nodes.end(); node++) {
if (saveData) {
- cachefile << (*node)->getIndex () << " "
- << (*node)->getElevationM (parent->getElevation()*SG_FEET_TO_METER) << " "
+ cachefile << node->second->getIndex () << " "
+ << node->second->getElevationM (parent->getElevation()*SG_FEET_TO_METER) << " "
<< endl;
}
}
}
}
-void FGGroundNetwork::addSegment(const FGTaxiSegment & seg)
+void FGGroundNetwork::addSegment(FGTaxiSegment* seg)
{
- segments.push_back(new FGTaxiSegment(seg));
+ segments.push_back(seg);
}
-void FGGroundNetwork::addNode(const FGTaxiNode & node)
+void FGGroundNetwork::addNode(FGTaxiNode* node)
{
- nodes.push_back(new FGTaxiNode(node));
+ assert(node);
+ IndexTaxiNodeMap::iterator it = nodes.find(node->getIndex());
+ if (it != nodes.end()) {
+ throw sg_range_exception();
+ }
+
+ nodes.insert(it, std::make_pair(node->getIndex(), node));
}
void FGGroundNetwork::addNodes(FGParkingVec * parkings)
{
- FGTaxiNode n;
- FGParkingVecIterator i = parkings->begin();
- while (i != parkings->end()) {
- n.setIndex(i->getIndex());
- n.setLatitude(i->getLatitude());
- n.setLongitude(i->getLongitude());
- n.setElevation(parent->getElevation()*SG_FEET_TO_METER);
- nodes.push_back(new FGTaxiNode(n));
-
- i++;
- }
+ BOOST_FOREACH(FGParking* parking, *parkings) {
+ addNode(parking);
+ }
}
-
-
void FGGroundNetwork::init()
{
if (networkInitialized) {
hasNetwork = true;
nextSave = 0;
int index = 1;
- sort(nodes.begin(), nodes.end(), compare_nodes);
- //sort(segments.begin(), segments.end(), compare_segments());
- FGTaxiSegmentVectorIterator i = segments.begin();
- while (i != segments.end()) {
- (*i)->setStart(&nodes);
- (*i)->setEnd(&nodes);
- (*i)->setDimensions(parent->getElevation() * SG_FEET_TO_METER);
- (*i)->setIndex(index);
- if ((*i)->isPushBack()) {
- pushBackNodes.push_back((*i)->getEnd());
- }
- //SG_LOG(SG_GENERAL, SG_BULK, "initializing segment " << (*i)->getIndex() << endl);
- //SG_LOG(SG_GENERAL, SG_BULK, "Track distance = " << (*i)->getLength() << endl);
- //SG_LOG(SG_GENERAL, SG_BULK, "Track runs from " << (*i)->getStart()->getIndex() << " to "
- // << (*i)->getEnd()->getIndex() << endl);
- i++;
- index++;
- }
-
- i = segments.begin();
- while (i != segments.end()) {
- FGTaxiSegmentVectorIterator j = (*i)->getEnd()->getBeginRoute();
- while (j != (*i)->getEnd()->getEndRoute()) {
- if ((*j)->getEnd()->getIndex() == (*i)->getStart()->getIndex()) {
-// int start1 = (*i)->getStart()->getIndex();
-// int end1 = (*i)->getEnd() ->getIndex();
-// int start2 = (*j)->getStart()->getIndex();
-// int end2 = (*j)->getEnd()->getIndex();
-// int oppIndex = (*j)->getIndex();
- //cerr << "Opposite of " << (*i)->getIndex() << " (" << start1 << "," << end1 << ") "
- // << "happens to be " << oppIndex << " (" << start2 << "," << end2 << ") " << endl;
- (*i)->setOpposite(*j);
- break;
- }
- j++;
- }
- i++;
+
+ // bind segments to nodes
+ BOOST_FOREACH(FGTaxiSegment* segment, segments) {
+ if (!segment->bindToNodes(nodes)) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "unable to bind taxiway segment");
+ }
+
+ segment->setIndex(index++);
+ if (segment->isPushBack()) {
+ pushBackNodes.push_back(segment->getEnd());
+ }
+ }
+
+ // establish pairing of segments
+ BOOST_FOREACH(FGTaxiSegment* segment, segments) {
+ FGTaxiSegment* opp = segment->getEnd()->getArcTo(segment->getStart());
+ if (opp) {
+ segment->setOpposite(opp);
+ }
}
- //FGTaxiNodeVectorIterator j = nodes.begin();
- //while (j != nodes.end()) {
- // if ((*j)->getHoldPointType() == 3) {
- // pushBackNodes.push_back((*j));
- // }
- // j++;
- //}
- //cerr << "Done initializing ground network" << endl;
- //exit(1);
+
if (fgGetBool("/sim/ai/groundnet-cache")) {
- SGPath cacheData(globals->get_fg_home());
- cacheData.append("ai");
- string airport = parent->getId();
+ parseCache();
+ }
+
+ networkInitialized = true;
+}
- 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);
- }
- }
- }
- }
+void FGGroundNetwork::parseCache()
+{
+ SGPath cacheData(globals->get_fg_home());
+ cacheData.append("ai");
+ string airport = parent->getId();
+
+ if (airport.empty()) {
+ return;
+ }
+
+ 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 (IndexTaxiNodeMap::iterator i = nodes.begin();
+ i != nodes.end();
+ i++) {
+ i->second->setElevation(parent->elevation() * SG_FEET_TO_METER);
+ data >> index >> elev;
+ if (data.eof())
+ break;
+ if (index != i->second->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->second->setElevation(elev);
}
+ }
}
- //cerr << "Finished initializing " << parent->getId() << " groundnetwork " << endl;
- networkInitialized = true;
+ }
}
int FGGroundNetwork::findNearestNode(const SGGeod & aGeod)
double minDist = HUGE_VAL;
int index = -1;
- for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end();
- itr++) {
- double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
+ IndexTaxiNodeMap::iterator i;
+ for (i = nodes.begin(); i != nodes.end(); i++) {
+ double d = SGGeodesy::distanceM(aGeod, i->second->geod());
if (d < minDist) {
minDist = d;
- index = (*itr)->getIndex();
- //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
+ index = i->first;
}
}
double minDist = HUGE_VAL;
int index = -1;
- for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end();
- itr++) {
- if (!((*itr)->getIsOnRunway())) {
+ IndexTaxiNodeMap::iterator i;
+ for (i = nodes.begin(); i != nodes.end(); i++) {
+ if (!i->second->getIsOnRunway()) {
continue;
}
- double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
+
+ double d = SGGeodesy::distanceM(aGeod, i->second->geod());
if (d < minDist) {
minDist = d;
- index = (*itr)->getIndex();
- //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
+ index = i->first;
}
}
return index;
}
-
-int FGGroundNetwork::findNearestNode(double lat, double lon)
-{
- return findNearestNode(SGGeod::fromDeg(lon, lat));
-}
-
-FGTaxiNode *FGGroundNetwork::findNode(unsigned idx)
-{ /*
- for (FGTaxiNodeVectorIterator
- itr = nodes.begin();
- itr != nodes.end(); itr++)
- {
- if (itr->getIndex() == idx)
- return itr->getAddress();
- } */
-
- if (idx < nodes.size())
- return nodes[idx]->getAddress();
- else
- return 0;
+FGTaxiNode* FGGroundNetwork::findNode(unsigned int idx)
+{
+ IndexTaxiNodeMap::iterator i = nodes.find(idx);
+ if (i == nodes.end()) {
+ return NULL;
+ }
+
+ return i->second;
}
FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx)
}
*/
if ((idx > 0) && (idx <= segments.size()))
- return segments[idx - 1]->getAddress();
+ return segments[idx - 1];
else {
//cerr << "Alert: trying to find invalid segment " << idx << endl;
return 0;
//double INFINITE = 100000000000.0;
// initialize scoring values
int nParkings = parent->getDynamics()->getNrOfParkings();
- FGTaxiNodeVector *currNodesSet;
+ FGTaxiNodeVector unvisited;
+
if (fullSearch) {
- currNodesSet = &nodes;
+ // create vector from map values
+ IndexTaxiNodeMap::iterator i;
+ for (i = nodes.begin(); i != nodes.end(); i++) {
+ unvisited.push_back(i->second);
+ }
} else {
- currNodesSet = &pushBackNodes;
+ unvisited = pushBackNodes;
}
-
- for (FGTaxiNodeVectorIterator
- itr = currNodesSet->begin(); itr != currNodesSet->end(); itr++) {
- (*itr)->setPathScore(HUGE_VAL); //infinity by all practical means
- (*itr)->setPreviousNode(0); //
- (*itr)->setPreviousSeg(0); //
+
+ BOOST_FOREACH(FGTaxiNode* node, unvisited) {
+ node->setPathScore(HUGE_VAL); //infinity by all practical means
+ node->setPreviousNode(0); //
+ node->setPreviousSeg(0); //
}
FGTaxiNode *firstNode = findNode(start);
return FGTaxiRoute();
}
- FGTaxiNodeVector unvisited(*currNodesSet); // working copy
-
while (!unvisited.empty()) {
- FGTaxiNode *best = *(unvisited.begin());
- for (FGTaxiNodeVectorIterator
- itr = unvisited.begin(); itr != unvisited.end(); itr++) {
- if ((*itr)->getPathScore() < best->getPathScore())
- best = (*itr);
+ FGTaxiNode *best = unvisited.front();
+ BOOST_FOREACH(FGTaxiNode* i, unvisited) {
+ if (i->getPathScore() < best->getPathScore()) {
+ best = i;
+ }
}
+ // remove 'best' from the unvisited set
FGTaxiNodeVectorIterator newend =
remove(unvisited.begin(), unvisited.end(), best);
unvisited.erase(newend, unvisited.end());
if (best == lastNode) { // found route or best not connected
break;
- } else {
- for (FGTaxiSegmentVectorIterator
- seg = best->getBeginRoute();
- seg != best->getEndRoute(); seg++) {
- if (fullSearch || (*seg)->isPushBack()) {
- FGTaxiNode *tgt = (*seg)->getEnd();
- if (!tgt)
- {
- SG_LOG(SG_GENERAL, SG_ALERT,
- "Error in ground network. Found empty segment "
- << " at " << ((parent) ? parent->getId() : "<unknown>"));
- return FGTaxiRoute();
- }
- double alt =
- best->getPathScore() + (*seg)->getLength() +
- (*seg)->getPenalty(nParkings);
- if (alt < tgt->getPathScore()) { // Relax (u,v)
- tgt->setPathScore(alt);
- tgt->setPreviousNode(best);
- tgt->setPreviousSeg(*seg); //
- }
- } else {
- // // cerr << "Skipping TaxiSegment " << (*seg)->getIndex() << endl;
- }
- }
}
- }
+
+ BOOST_FOREACH(FGTaxiSegment* seg, best->arcs()) {
+ if (!fullSearch && !seg->isPushBack()) {
+ continue; // inelligible!
+ }
+
+ FGTaxiNode *tgt = seg->getEnd();
+ double alt = best->getPathScore() + seg->getLength() +
+ seg->getPenalty(nParkings);
+ if (alt < tgt->getPathScore()) { // Relax (u,v)
+ tgt->setPathScore(alt);
+ tgt->setPreviousNode(best);
+ tgt->setPreviousSeg(seg);
+ }
+ } // of outgoing arcs/segments from current best node iteration
+ } // of unvisited nodes remaining
if (lastNode->getPathScore() == HUGE_VAL) {
// no valid route found
}
bool origStatus = current->hasHoldPosition();
current->setHoldPosition(false);
- SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
+ //SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
int currentRoute = i->getCurrentPosition();
int nextRoute;
if (i->getIntentions().size()) {
// current->setHoldPosition(true);
//}
SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
- SGGeod end (SGGeod::fromDeg(nx->getStart()->getLongitude(), nx->getStart()->getLatitude()));
+ SGGeod end (nx->getStart()->geod());
double distance = SGGeodesy::distanceM(start, end);
if (nx->hasBlock(now) && (distance < i->getRadius() * 4)) {
if (pos >= 0) {
SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
- SGGeod end (SGGeod::fromDeg(segments[pos]->getEnd()->getLongitude(), segments[pos]->getEnd()->getLatitude()));
+ SGGeod end (segments[pos]->getEnd()->geod());
double length = SGGeodesy::distanceM(start, end);
- //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
+ //heading = SGGeodesy::headingDeg(start->geod(), end->geod());
double az2, heading; //, distanceM;
SGGeodesy::inverse(start, end, heading, az2, length);
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();
+ SGGeod center2 = segments[k]->getStart()->geod();
center2.setElevationM(SG_MAX_ELEVATION_M);
if (local_scenery->get_elevation_m( center2, elevationStart, NULL )) {
// elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5;
segments[k]->getStart()->setElevation(elevationStart);
}
if ((elevationEnd == 0) || (elevationEnd == parent->getElevation())) {
- SGGeod center2 = segments[k]->getEnd()->getGeod();
+ SGGeod center2 = segments[k]->getEnd()->geod();
center2.setElevationM(SG_MAX_ELEVATION_M);
if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
// elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
// 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 );
+ SGGeod segCenter = segments[k]->getCenter();
+ WorldCoordinate( obj_pos, segCenter.getLatitudeDeg(), segCenter.getLongitudeDeg(), elevationMean+ 0.5, -(segments[k]->getHeading()), slope );
obj_trans->setMatrix( obj_pos );
//osg::Vec3 center(0, 0, 0)
#ifndef _GROUNDNETWORK_HXX_
#define _GROUNDNETWORK_HXX_
-#include <osg/Geode>
-#include <osg/Geometry>
-#include <osg/MatrixTransform>
-#include <osg/Shape>
-
-
#include <simgear/compiler.h>
#include <string>
#include <vector>
#include <list>
+#include <map>
class Block;
class FGAirport; // forward reference
typedef std::vector<FGTaxiSegment*> FGTaxiSegmentVector;
-typedef std::vector<FGTaxiSegment*>::iterator FGTaxiSegmentVectorIterator;
+typedef FGTaxiSegmentVector::iterator FGTaxiSegmentVectorIterator;
-//typedef vector<FGTaxiSegment*> FGTaxiSegmentPointerVector;
-//typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentPointerVectorIterator;
+typedef std::map<int, FGTaxiNode_ptr> IndexTaxiNodeMap;
class Block
{
int endNode;
double length;
double heading;
- SGGeod center;
bool isActive;
bool isPushBackRoute;
BlockList blockTimes;
int index;
FGTaxiSegment *oppositeDirection;
-
-
public:
- FGTaxiSegment() :
- startNode(0),
- endNode(0),
- length(0),
- heading(0),
- isActive(0),
- isPushBackRoute(0),
- start(0),
- end(0),
- index(0),
- oppositeDirection(0)
- {
- };
-
- FGTaxiSegment (const FGTaxiSegment &other) :
- startNode (other.startNode),
- endNode (other.endNode),
- length (other.length),
- heading (other.heading),
- center (other.center),
- isActive (other.isActive),
- isPushBackRoute (other.isPushBackRoute),
- blockTimes (other.blockTimes),
- start (other.start),
- end (other.end),
- index (other.index),
- oppositeDirection (other.oppositeDirection)
- {
- };
-
- FGTaxiSegment& operator=(const FGTaxiSegment &other)
- {
- startNode = other.startNode;
- endNode = other.endNode;
- length = other.length;
- heading = other.heading;
- center = other.center;
- isActive = other.isActive;
- isPushBackRoute = other.isPushBackRoute;
- blockTimes = other.blockTimes;
- start = other.start;
- end = other.end;
- index = other.index;
- oppositeDirection = other.oppositeDirection;
- return *this;
- };
-
+ FGTaxiSegment(int start, int end, bool isPushBack);
+
void setIndex (int val) {
index = val;
};
- void setStartNodeRef (int val) {
- startNode = val;
- };
- void setEndNodeRef (int val) {
- endNode = val;
- };
void setOpposite(FGTaxiSegment *opp) {
oppositeDirection = opp;
};
- void setStart(FGTaxiNodeVector *nodes);
- void setEnd (FGTaxiNodeVector *nodes);
- void setPushBackType(bool val) {
- isPushBackRoute = val;
- };
+ bool bindToNodes(const IndexTaxiNodeMap& nodes);
+
void setDimensions(double elevation);
void block(int id, time_t blockTime, time_t now);
void unblock(time_t now);
int getIndex() {
return index;
};
- double getLatitude() {
- return center.getLatitudeDeg();
- };
- double getLongitude() {
- return center.getLongitudeDeg();
- };
+
+ // compute the center of the arc
+ SGGeod getCenter() const;
+
double getHeading() {
return heading;
};
int getPenalty(int nGates);
- FGTaxiSegment *getAddress() {
- return this;
- };
-
bool operator<(const FGTaxiSegment &other) const {
return index < other.index;
};
FGTaxiSegment *opposite() {
return oppositeDirection;
};
- void setCourseDiff(double crse);
-
-
-
-
};
//int maxDepth;
int count;
int version;
- FGTaxiNodeVector nodes;
- FGTaxiNodeVector pushBackNodes;
+
+ IndexTaxiNodeMap nodes;
+ FGTaxiNodeVector pushBackNodes;
+
FGTaxiSegmentVector segments;
- //intVec route;
- //intVec nodesStack;
- //intVec routesStack;
+
TaxiRouteVector routes;
TrafficVector activeTraffic;
TrafficVectorIterator currTraffic;
double heading, double speed, double alt);
-
+ void parseCache();
public:
FGGroundNetwork();
~FGGroundNetwork();
- void addNode (const FGTaxiNode& node);
+ void addNode (FGTaxiNode* node);
void addNodes (FGParkingVec *parkings);
- void addSegment(const FGTaxiSegment& seg);
+ void addSegment(FGTaxiSegment* seg);
void setVersion (int v) { version = v;};
int getVersion() { return version; };
towerController = twrCtrlr;
};
- int findNearestNode(double lat, double lon);
int findNearestNode(const SGGeod& aGeod);
int findNearestNodeOnRunway(const SGGeod& aGeod);
/*********************************************************************************
* FGParking
********************************************************************************/
-// FGParking::FGParking(double lat,
-// double lon,
-// double hdg,
-// double rad,
-// int idx,
-// const string &name,
-// const string &tpe,
-// const string &codes)
-// : FGTaxiNode(lat,lon,idx)
-// {
-// heading = hdg;
-// parkingName = name;
-// type = tpe;
-// airlineCodes = codes;
-// }
-FGParking::~FGParking() {
- delete pushBackRoute;
+
+FGParking::FGParking(PositionedID aGuid, int index, const SGGeod& pos,
+ double aHeading, double aRadius,
+ const std::string& name, const std::string& aType,
+ const std::string& codes) :
+ FGTaxiNode(aGuid, index, pos, false, 0),
+ heading(aHeading),
+ radius(aRadius),
+ parkingName(name),
+ type(aType),
+ airlineCodes(codes),
+ available(true),
+ pushBackPoint(0)
+{
+}
+
+FGParking::~FGParking()
+{
}
#endif
#include <simgear/compiler.h>
+#include <simgear/sg_inlines.h>
#include <string>
#include <vector>
+#include <memory> // for std::auto_ptr
#include "gnnode.hxx"
class FGTaxiRoute;
-class FGParking : public FGTaxiNode {
+class FGParking : public FGTaxiNode
+{
private:
double heading;
double radius;
bool available;
int pushBackPoint;
- FGTaxiRoute *pushBackRoute;
+ std::auto_ptr<FGTaxiRoute> pushBackRoute;
+ SG_DISABLE_COPY(FGParking);
public:
- FGParking() :
- heading(0),
- radius(0),
- available(true),
- pushBackPoint(0),
- pushBackRoute(0)
- {
- };
-
- FGParking(const FGParking &other) :
- FGTaxiNode (other),
- heading (other.heading),
- radius (other.radius),
- parkingName (other.parkingName),
- type (other.type),
- airlineCodes (other.airlineCodes),
- available (other.available),
- pushBackPoint(other.pushBackPoint),
- pushBackRoute(other.pushBackRoute)
- {
- };
-
-
- FGParking& operator =(const FGParking &other)
- {
- FGTaxiNode::operator=(other);
- heading = other.heading;
- radius = other.radius;
- parkingName = other.parkingName;
- type = other.type;
- airlineCodes = other.airlineCodes;
- available = other.available;
- pushBackPoint= other.pushBackPoint;
- pushBackRoute= other.pushBackRoute;
- return *this;
- };
- ~FGParking();
+ FGParking(PositionedID aGuid, int index, const SGGeod& pos,
+ double heading, double radius,
+ const std::string& name, const std::string& type,
+ const std::string& codes);
+ virtual ~FGParking();
void setHeading (double hdg) { heading = hdg; };
void setRadius (double rad) { radius = rad; };
void setType (const std::string& tpe) { type = tpe; };
void setCodes (const std::string& codes){ airlineCodes= codes;};
- void setPushBackRoute(FGTaxiRoute *val) { pushBackRoute = val; };
+ void setPushBackRoute(std::auto_ptr<FGTaxiRoute> val) { pushBackRoute = val; };
void setPushBackPoint(int val) { pushBackPoint = val; };
bool isAvailable () const { return available;};
std::string getCodes () const { return airlineCodes;};
std::string getName () const { return parkingName; };
- FGTaxiRoute * getPushBackRoute () { return pushBackRoute; };
+ FGTaxiRoute * getPushBackRoute () { return pushBackRoute.get(); };
int getPushBackPoint () { return pushBackPoint; };
return radius < other.radius; };
};
-typedef std::vector<FGParking> FGParkingVec;
-typedef std::vector<FGParking>::iterator FGParkingVecIterator;
-typedef std::vector<FGParking>::const_iterator FGParkingVecConstIterator;
+typedef std::vector<FGParking*> FGParkingVec;
+typedef FGParkingVec::iterator FGParkingVecIterator;
+typedef FGParkingVec::const_iterator FGParkingVecConstIterator;
#endif
FGParking* parking = dcs->getParking(gateID);
parking->setAvailable(false);
- fgApplyStartOffset(parking->getGeod(), parking->getHeading());
+ fgApplyStartOffset(parking->geod(), parking->getHeading());
return true;
}
case RUNWAY: return "runway";
case TAXIWAY: return "taxiway";
case PAVEMENT: return "pavement";
- case PARK_STAND: return "parking stand";
+ case PARKING: return "parking stand";
case FIX: return "fix";
case VOR: return "VOR";
case NDB: return "NDB";
case FREQ_CLEARANCE: return "clearance";
case FREQ_UNICOM: return "unicom";
case FREQ_APP_DEP: return "approach-departure";
+ case TAXI_NODE: return "taxi-node";
default:
return "unknown";
}
#include <vector>
#include <stdint.h>
+#include <simgear/sg_inlines.h>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/math/SGMath.hxx>
RUNWAY,
TAXIWAY,
PAVEMENT,
- PARK_STAND,
WAYPOINT,
FIX,
NDB,
FREQ_ENROUTE,
FREQ_CLEARANCE,
FREQ_UNICOM,
+// groundnet items
+ PARKING, ///< parking position - might be a gate, or stand
+ TAXI_NODE,
LAST_TYPE
} Type;
const SGVec3d mCart;
const Type mType;
const std::string mIdent;
+
+private:
+ SG_DISABLE_COPY(FGPositioned);
};
#endif // of FG_POSITIONED_HXX
continue;
}
- const SGGeod& parkLoc = park->getGeod();
+ const SGGeod& parkLoc = park->geod();
naRef ph = naNewHash(c);
hashset(c, ph, "name", stringToNasal(c, park->getName()));
hashset(c, ph, "lat", naNum(parkLoc.getLatitudeDeg()));