1 // groundnet.cxx - Implimentation of the FlightGear airport ground handling code
3 // Written by Durk Talsma, started June 2005.
5 // Copyright (C) 2004 Durk Talsma.
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 # define _USE_MATH_DEFINES
33 #include <simgear/compiler.h>
35 //#include <plib/sg.h>
36 //#include <plib/ul.h>
38 //#include <Environment/environment_mgr.hxx>
39 //#include <Environment/environment.hxx>
40 //#include <simgear/misc/sg_path.hxx>
41 //#include <simgear/props/props.hxx>
42 //#include <simgear/structure/subsystem_mgr.hxx>
43 #include <simgear/debug/logstream.hxx>
44 #include <simgear/route/waypoint.hxx>
45 //#include <Main/globals.hxx>
46 //#include <Main/fg_props.hxx>
47 //#include <Airports/runways.hxx>
51 #include "groundnetwork.hxx"
55 /**************************************************************************
57 *************************************************************************/
58 FGTaxiNode::FGTaxiNode()
62 /***************************************************************************
64 **************************************************************************/
65 FGTaxiSegment::FGTaxiSegment()
69 void FGTaxiSegment::setStart(FGTaxiNodeVector *nodes)
71 FGTaxiNodeVectorIterator i = nodes->begin();
72 while (i != nodes->end())
74 if (i->getIndex() == startNode)
76 start = i->getAddress();
84 void FGTaxiSegment::setEnd(FGTaxiNodeVector *nodes)
86 FGTaxiNodeVectorIterator i = nodes->begin();
87 while (i != nodes->end())
89 if (i->getIndex() == endNode)
91 end = i->getAddress();
98 // There is probably a computationally cheaper way of
100 void FGTaxiSegment::setTrackDistance()
103 SGWayPoint first (start->getLongitude(),
104 start->getLatitude(),
106 SGWayPoint second (end->getLongitude(),
109 first.CourseAndDistance(second, &course, &length);
113 bool FGTaxiRoute::next(int *val)
115 //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
116 // cerr << "FGTaxiRoute contains : " << *(i) << endl;
117 //cerr << "Offset from end: " << nodes.end() - currNode << endl;
118 //if (currNode != nodes.end())
119 // cerr << "true" << endl;
121 // cerr << "false" << endl;
123 if (currNode == nodes.end())
129 /***************************************************************************
131 **************************************************************************/
133 FGGroundNetwork::FGGroundNetwork()
141 void FGGroundNetwork::addSegment(const FGTaxiSegment &seg)
143 segments.push_back(seg);
146 void FGGroundNetwork::addNode(const FGTaxiNode &node)
148 nodes.push_back(node);
151 void FGGroundNetwork::addNodes(FGParkingVec *parkings)
154 FGParkingVecIterator i = parkings->begin();
155 while (i != parkings->end())
157 n.setIndex(i->getIndex());
158 n.setLatitude(i->getLatitude());
159 n.setLongitude(i->getLongitude());
168 void FGGroundNetwork::init()
171 FGTaxiSegmentVectorIterator i = segments.begin();
172 while(i != segments.end()) {
173 //cerr << "initializing node " << i->getIndex() << endl;
176 i->setTrackDistance();
177 //cerr << "Track distance = " << i->getLength() << endl;
178 //cerr << "Track ends at" << i->getEnd()->getIndex() << endl;
184 int FGGroundNetwork::findNearestNode(double lat, double lon)
186 double minDist = HUGE_VAL;
189 SGWayPoint first (lon,
193 for (FGTaxiNodeVectorIterator
195 itr != nodes.end(); itr++)
198 SGWayPoint second (itr->getLongitude(),
201 first.CourseAndDistance(second, &course, &dist);
205 index = itr->getIndex();
206 //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
212 FGTaxiNode *FGGroundNetwork::findNode(int idx)
214 for (FGTaxiNodeVectorIterator
216 itr != nodes.end(); itr++)
218 if (itr->getIndex() == idx)
219 return itr->getAddress();
224 FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end)
228 FGTaxiNode *firstNode = findNode(start);
229 FGTaxiNode *lastNode = findNode(end);
230 //prevNode = prevPrevNode = -1;
234 trace(firstNode, end, 0, 0);
239 SG_LOG( SG_GENERAL, SG_INFO, "Failed to find route from waypoint " << start << " to " << end );
242 sort(routes.begin(), routes.end());
243 //for (intVecIterator i = route.begin(); i != route.end(); i++)
245 // rte->push_back(*i);
248 if (routes.begin() != routes.end())
249 return *(routes.begin());
255 void FGGroundNetwork::trace(FGTaxiNode *currNode, int end, int depth, double distance)
257 traceStack.push_back(currNode->getIndex());
258 totalDistance += distance;
259 //cerr << "Starting trace " << depth << " total distance: " << totalDistance<< endl;
260 //<< currNode->getIndex() << endl;
262 // If the current route matches the required end point we found a valid route
263 // So we can add this to the routing table
264 if (currNode->getIndex() == end)
266 //cerr << "Found route : " << totalDistance << "" << " " << *(traceStack.end()-1) << endl;
267 routes.push_back(FGTaxiRoute(traceStack,totalDistance));
268 traceStack.pop_back();
270 maxDistance = totalDistance;
272 if (totalDistance < maxDistance)
273 maxDistance = totalDistance;
275 totalDistance -= distance;
280 // search if the currentNode has been encountered before
281 // if so, we should step back one level, because it is
282 // rather rediculous to proceed further from here.
283 // if the current node has not been encountered before,
284 // i should point to traceStack.end()-1; and we can continue
285 // if i is not traceStack.end, the previous node was found,
286 // and we should return.
287 // This only works at trace levels of 1 or higher though
289 intVecIterator i = traceStack.begin();
290 while ((*i) != currNode->getIndex()) {
291 //cerr << "Route so far : " << (*i) << endl;
294 if (i != traceStack.end()-1) {
295 traceStack.pop_back();
296 totalDistance -= distance;
299 // If the total distance from start to the current waypoint
300 // is longer than that of a route we can also stop this trace
301 // and go back one level.
302 if ((totalDistance > maxDistance) && foundRoute)
304 //cerr << "Stopping rediculously long trace: " << totalDistance << endl;
305 traceStack.pop_back();
306 totalDistance -= distance;
311 //cerr << "2" << endl;
312 if (currNode->getBeginRoute() != currNode->getEndRoute())
314 //cerr << "3" << endl;
315 for (FGTaxiSegmentPointerVectorIterator
316 i = currNode->getBeginRoute();
317 i != currNode->getEndRoute();
320 //cerr << (*i)->getLenght() << endl;
321 trace((*i)->getEnd(), end, depth+1, (*i)->getLength());
323 // // cerr << currNode -> getIndex() << " ";
324 // route.push_back(currNode->getIndex());
331 SG_LOG( SG_GENERAL, SG_DEBUG, "4" );
333 traceStack.pop_back();
334 totalDistance -= distance;