1
0
Fork 0

Make FGTaxiNode and FGParking inherit FGPositioned.

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.
This commit is contained in:
James Turner 2012-09-25 00:31:17 +01:00
parent a2cfef95fb
commit b1ff365a8f
17 changed files with 504 additions and 730 deletions

View file

@ -313,7 +313,7 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
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() << " ";
@ -356,7 +356,7 @@ void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
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);
}
@ -419,7 +419,7 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
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);
@ -969,14 +969,14 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
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);
}
}
@ -1024,18 +1024,18 @@ bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
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;

View file

@ -93,8 +93,7 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
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();
@ -111,7 +110,7 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
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);
@ -126,34 +125,29 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
//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;

View file

@ -1340,10 +1340,10 @@ void FGStartupController::render(bool visible)
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);
@ -1428,7 +1428,7 @@ void FGStartupController::render(bool visible)
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;
@ -1440,7 +1440,7 @@ void FGStartupController::render(bool visible)
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;
@ -1459,8 +1459,9 @@ void FGStartupController::render(bool visible)
//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()) );

View file

@ -21,8 +21,32 @@
#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;
@ -32,150 +56,142 @@ void FGAirportDynamicsXMLLoader::endXML () {
//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);
}
if (name == string("arc"))
{
taxiSegment.setIndex(++index);
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)));
}
_dynamics->getGroundNetwork()->addSegment(taxiSegment);
}
// sort by radius, in asending order, so that smaller gates are first in the list
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::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::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;
}
}
}
SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat)));
FGTaxiNode* taxiNode = new FGTaxiNode(0, index, pos, onRunway, holdPointType);
_dynamics->getGroundNetwork()->addNode(taxiNode);
}
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::startArc(const XMLAttributes &atts)
{
int begin, end;
bool isPushBackRoute = false;
for (int i = 0; i < atts.size() ; 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(new FGTaxiSegment(begin, end, isPushBackRoute));
}
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);
}
}
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) {

View file

@ -35,6 +35,10 @@ protected:
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;
};

View file

@ -91,8 +91,7 @@ int FGAirportDynamics::innerGetAvailableParking(double radius, const string & fl
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;
@ -151,49 +150,43 @@ int FGAirportDynamics::getAvailableParking(double radius, const string & flType,
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);
}
}
}
@ -380,7 +373,7 @@ string FGAirportDynamics::chooseRunwayFallback()
return rwy->ident();
}
void FGAirportDynamics::addParking(FGParking & park)
void FGAirportDynamics::addParking(FGParking* park)
{
parkings.push_back(park);
}

View file

@ -99,7 +99,7 @@ public:
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

View file

@ -1,99 +1,63 @@
#include "gnnode.hxx"
#include <boost/foreach.hpp>
#include "groundnetwork.hxx"
#include <iostream>
#include <algorithm>
#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
*************************************************************************/
FGTaxiNode::FGTaxiNode(PositionedID aGuid, int index, const SGGeod& pos, bool aOnRunway, int aHoldType) :
FGPositioned(aGuid, FGPositioned::PARKING, "", pos),
index(index),
isOnRunway(aOnRunway),
holdType(aHoldType)
{
}
FGTaxiNode::~FGTaxiNode()
{
}
void FGTaxiNode::setElevation(double val)
{
geod.setElevationM(val);
// ignored for the moment
}
void FGTaxiNode::setLatitude (double val)
{
geod.setLatitudeDeg(val);
}
void FGTaxiNode::setLongitude(double val)
{
geod.setLongitudeDeg(val);
}
void FGTaxiNode::setLatitude (const string& val)
{
geod.setLatitudeDeg(processPosition(val));
}
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;
}

View file

@ -20,76 +20,39 @@
#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; };
@ -99,26 +62,28 @@ FGTaxiNode &operator =(const FGTaxiNode &other)
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

View file

@ -27,7 +27,7 @@
#include <math.h>
#include <algorithm>
#include <fstream>
#include <boost/foreach.hpp>
#include <osg/Geode>
#include <osg/Geometry>
@ -39,6 +39,7 @@
#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>
@ -59,64 +60,47 @@ using std::string;
* 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);
};
bool FGTaxiSegment::bindToNodes(const IndexTaxiNodeMap& nodes)
{
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;
}
void FGTaxiSegment::setEnd(FGTaxiNodeVector * nodes)
SGGeod FGTaxiSegment::getCenter() const
{
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);
return SGGeodesy::direct(start->geod(), heading, length * 0.5);
}
// There is probably a computationally cheaper way of
// doing this.
void FGTaxiSegment::setDimensions(double elevation)
{
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;
}
//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();
@ -193,7 +177,7 @@ bool FGTaxiRoute::next(int *nde, int *rte)
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;
@ -237,15 +221,6 @@ void FGTaxiRoute::rewind(int route)
/***************************************************************************
* 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)
{
@ -344,11 +319,11 @@ void FGGroundNetwork::saveElevationCache() {
}
}
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;
}
}
@ -357,33 +332,29 @@ void FGGroundNetwork::saveElevationCache() {
}
}
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) {
@ -394,110 +365,90 @@ void FGGroundNetwork::init()
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++;
// 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());
}
}
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++;
// 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();
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);
}
}
}
}
}
parseCache();
}
//cerr << "Finished initializing " << parent->getId() << " groundnetwork " << endl;
networkInitialized = true;
}
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);
}
}
}
}
}
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;
}
}
@ -509,42 +460,30 @@ int FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod)
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)
@ -558,7 +497,7 @@ 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;
@ -575,18 +514,22 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end,
//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);
@ -608,49 +551,38 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end,
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
@ -1080,7 +1012,7 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
}
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()) {
@ -1100,7 +1032,7 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
// 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)) {
@ -1379,10 +1311,10 @@ void FGGroundNetwork::render(bool visible)
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);
@ -1466,7 +1398,7 @@ void FGGroundNetwork::render(bool visible)
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;
@ -1478,7 +1410,7 @@ void FGGroundNetwork::render(bool visible)
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;
@ -1497,8 +1429,8 @@ void FGGroundNetwork::render(bool visible)
// 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)

View file

@ -24,17 +24,12 @@
#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;
@ -48,10 +43,9 @@ class FGAIFlightPlan; // forward reference
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
{
@ -82,7 +76,6 @@ private:
int endNode;
double length;
double heading;
SGGeod center;
bool isActive;
bool isPushBackRoute;
BlockList blockTimes;
@ -91,75 +84,19 @@ private:
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);
@ -177,12 +114,10 @@ public:
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;
};
@ -192,10 +127,6 @@ public:
int getPenalty(int nGates);
FGTaxiSegment *getAddress() {
return this;
};
bool operator<(const FGTaxiSegment &other) const {
return index < other.index;
};
@ -203,11 +134,6 @@ public:
FGTaxiSegment *opposite() {
return oppositeDirection;
};
void setCourseDiff(double crse);
};
@ -304,12 +230,12 @@ private:
//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;
@ -328,14 +254,14 @@ private:
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; };
@ -348,7 +274,6 @@ public:
towerController = twrCtrlr;
};
int findNearestNode(double lat, double lon);
int findNearestNode(const SGGeod& aGeod);
int findNearestNodeOnRunway(const SGGeod& aGeod);

View file

@ -36,21 +36,22 @@
/*********************************************************************************
* 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()
{
}

View file

@ -30,16 +30,19 @@
#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;
@ -49,46 +52,15 @@ private:
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; };
@ -97,7 +69,7 @@ public:
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;};
@ -110,7 +82,7 @@ public:
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; };
@ -118,8 +90,8 @@ public:
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

View file

@ -223,7 +223,7 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par
FGParking* parking = dcs->getParking(gateID);
parking->setAvailable(false);
fgApplyStartOffset(parking->getGeod(), parking->getHeading());
fgApplyStartOffset(parking->geod(), parking->getHeading());
return true;
}

View file

@ -143,7 +143,7 @@ const char* FGPositioned::nameForType(Type aTy)
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";
@ -166,6 +166,7 @@ const char* FGPositioned::nameForType(Type aTy)
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";
}

View file

@ -25,6 +25,7 @@
#include <vector>
#include <stdint.h>
#include <simgear/sg_inlines.h>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/math/SGMath.hxx>
@ -48,7 +49,6 @@ public:
RUNWAY,
TAXIWAY,
PAVEMENT,
PARK_STAND,
WAYPOINT,
FIX,
NDB,
@ -77,6 +77,9 @@ public:
FREQ_ENROUTE,
FREQ_CLEARANCE,
FREQ_UNICOM,
// groundnet items
PARKING, ///< parking position - might be a gate, or stand
TAXI_NODE,
LAST_TYPE
} Type;
@ -230,6 +233,9 @@ protected:
const SGVec3d mCart;
const Type mType;
const std::string mIdent;
private:
SG_DISABLE_COPY(FGPositioned);
};
#endif // of FG_POSITIONED_HXX

View file

@ -1350,7 +1350,7 @@ static naRef f_airport_parking(naContext c, naRef me, int argc, naRef* args)
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()));