00001 #ifndef _pathfinder_astar_generic_
00002 #define _pathfinder_astar_generic_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00032 #include "pathfinder.h"
00033
00034 #include <functional>
00035 #include <algorithm>
00036 #include <map>
00037
00038 namespace Pathfinder
00039 {
00040
00051 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE=double>
00052 class AStarGeneric
00053 {
00054 public:
00055 AStarGeneric();
00056 ~AStarGeneric();
00057
00058
00071 const PathResult FindPath(const NODETYPE &start, const NODETYPE &goal, std::vector<NODETYPE> &finalpath, DESTCOST &destinationcost, GETNEIGHBORS &getneighbors);
00072
00073
00082 void InitializeStep(const NODETYPE &start, const NODETYPE &goal, DESTCOST &destcost, GETNEIGHBORS &getneighbors);
00083
00089 const PathResult Step();
00090
00098 void GetPath(std::vector<NODETYPE> &path);
00099
00103 class AddNeighborFunctor
00104 {
00105 public:
00106 AddNeighborFunctor(AStarGeneric &astar):m_astargeneric(astar) {}
00113 inline void operator()(const NODETYPE &neighbor, const COSTTYPE &movecost)
00114 {
00115 m_astargeneric.AddNeighbor(neighbor,movecost);
00116 }
00117 private:
00118 AStarGeneric &m_astargeneric;
00119 };
00120
00124 class IGetNeighbors
00125 {
00126 public:
00127 virtual ~IGetNeighbors()=0;
00134 virtual void operator()(const NODETYPE &node, typename AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::AddNeighborFunctor &addneighborfunctor)=0;
00135 };
00136
00137 private:
00138
00139 AStarGeneric(const AStarGeneric &rhs);
00140 AStarGeneric &operator=(const AStarGeneric &rhs);
00141
00142 struct astarnode
00143 {
00144 NODETYPE m_node;
00145 astarnode *m_parent;
00146 COSTTYPE m_f;
00147 COSTTYPE m_g;
00148 COSTTYPE m_h;
00149 };
00150
00151 struct astarnodecompare:public std::binary_function<astarnode *, astarnode *, bool>
00152 {
00153 inline bool operator()(const astarnode *left, const astarnode *right)
00154 {
00155 return right->m_f<left->m_f;
00156 }
00157 };
00158
00159 class astarallocator:public std::allocator<astarnode>
00160 {
00161 public:
00162 astarallocator()
00163 {
00164 m_mempos=0;
00165 m_mem.resize(1000,NULL);
00166 }
00167
00168 ~astarallocator()
00169 {
00170 for(std::vector<astarnode *>::size_type i=0; i<m_mempos; i++)
00171 {
00172 delete m_mem[i];
00173 }
00174 }
00175
00176 pointer allocate(size_type count)
00177 {
00178 return m_mempos>0 ? m_mem[--m_mempos] : new astarnode;
00179 }
00180
00181 void deallocate(pointer ptr, size_type count)
00182 {
00183 if(m_mempos==m_mem.size())
00184 {
00185 m_mem.resize(m_mem.size()+1000,NULL);
00186 }
00187 m_mem[m_mempos++]=ptr;
00188 }
00189
00190 private:
00191 std::vector<astarnode *> m_mem;
00192 typename std::vector<astarnode *>::size_type m_mempos;
00193 };
00194
00195 struct listelement
00196 {
00197 listelement():m_node(NULL),m_onopen(false),m_onclosed(false) {}
00198 astarnode *m_node;
00199 bool m_onopen;
00200 bool m_onclosed;
00201 };
00202
00203 void ClearOpenList();
00204 void ClearClosedList();
00205 void AddNeighbor(const NODETYPE &neighbor, const COSTTYPE &movecost);
00206
00207 astarallocator m_astarnodeallocator;
00208
00209 std::vector<astarnode *> m_openlist;
00210 std::vector<astarnode *> m_closedlist;
00211 std::map<NODETYPE, listelement> m_helperlist;
00212
00213 astarnode *m_currentnode;
00214 astarnode *m_astaropen;
00215 const NODETYPE *m_start;
00216 const NODETYPE *m_goal;
00217 DESTCOST *m_destinationcost;
00218 GETNEIGHBORS *m_getneighbors;
00219
00220 };
00221
00222 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00223 AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::AStarGeneric():
00224 m_currentnode(0),m_astaropen(0),m_goal(0),m_destinationcost(0),m_getneighbors(0)
00225 {
00226
00227 }
00228
00229 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00230 AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::~AStarGeneric()
00231 {
00232 ClearOpenList();
00233 ClearClosedList();
00234 }
00235
00236 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00237 void AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::AddNeighbor(const NODETYPE &neighbor, const COSTTYPE &movecost)
00238 {
00239
00240 if(m_helperlist[neighbor].m_onclosed==false)
00241 {
00242
00243
00244 m_astaropen=m_helperlist[neighbor].m_node;
00245
00246
00247 if(m_astaropen!=NULL)
00248 {
00249 if(m_currentnode->m_g+movecost<m_astaropen->m_g)
00250 {
00251 m_astaropen->m_g=m_currentnode->m_g+movecost;
00252 m_astaropen->m_f=m_astaropen->m_g+m_astaropen->m_h;
00253 m_astaropen->m_parent=m_currentnode;
00254 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00255 }
00256 }
00257
00258 else
00259 {
00260 astarnode *newnode=m_astarnodeallocator.allocate(1);
00261 newnode->m_node=neighbor;
00262 newnode->m_parent=m_currentnode;
00263 newnode->m_g=m_currentnode->m_g+movecost;
00264 newnode->m_h=m_destinationcost->operator()(neighbor,*m_goal);
00265 newnode->m_f=newnode->m_g+newnode->m_h;
00266
00267 m_openlist.push_back(newnode);
00268 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00269 m_helperlist[newnode->m_node].m_onopen=true;
00270 m_helperlist[newnode->m_node].m_node=newnode;
00271 }
00272
00273 }
00274 }
00275
00276 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00277 void AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::ClearClosedList()
00278 {
00279 for(std::vector<astarnode *>::iterator i=m_closedlist.begin(); i!=m_closedlist.end(); i++)
00280 {
00281 m_astarnodeallocator.deallocate((*i),1);
00282 }
00283 m_closedlist.clear();
00284 }
00285
00286 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00287 void AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::ClearOpenList()
00288 {
00289 for(std::vector<astarnode *>::iterator i=m_openlist.begin(); i!=m_openlist.end(); i++)
00290 {
00291 m_astarnodeallocator.deallocate((*i),1);
00292 }
00293 m_openlist.clear();
00294 }
00295
00296 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00297 const PathResult AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::FindPath(const NODETYPE &start, const NODETYPE &goal, std::vector<NODETYPE> &finalpath, DESTCOST &destinationcost, GETNEIGHBORS &getneighbors)
00298 {
00299
00300 ClearOpenList();
00301 ClearClosedList();
00302 m_helperlist.clear();
00303
00304 m_astaropen=0;
00305 m_goal=&goal;
00306 m_destinationcost=&destinationcost;
00307 AddNeighborFunctor anf(*this);
00308
00309
00310 m_currentnode=0;
00311 astarnode *newnode=m_astarnodeallocator.allocate(1);
00312 newnode->m_node=start;
00313 newnode->m_parent=NULL;
00314 newnode->m_g=destinationcost(start,goal);
00315 newnode->m_h=0;
00316 newnode->m_f=newnode->m_g+newnode->m_h;
00317
00318
00319 m_openlist.push_back(newnode);
00320 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00321 m_helperlist[newnode->m_node].m_node=newnode;
00322 m_helperlist[newnode->m_node].m_onopen=true;
00323
00324 while(m_openlist.size()>0)
00325 {
00326 m_currentnode=m_openlist.front();
00327 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00328 m_openlist.pop_back();
00329 m_helperlist[m_currentnode->m_node].m_onopen=false;
00330
00331
00332 m_closedlist.push_back(m_currentnode);
00333 m_helperlist[m_currentnode->m_node].m_onclosed=true;
00334
00335 if(m_currentnode->m_node!=goal)
00336 {
00337 getneighbors(m_currentnode->m_node,anf);
00338 }
00339 else
00340 {
00341 finalpath.clear();
00342 while(m_currentnode)
00343 {
00344 finalpath.push_back(m_currentnode->m_node);
00345 m_currentnode=m_currentnode->m_parent;
00346 }
00347 return PATH_FOUND;
00348 }
00349
00350 }
00351
00352 return PATH_NOTFOUND;
00353 }
00354
00355 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00356 void AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::GetPath(std::vector<NODETYPE> &path)
00357 {
00358 path.clear();
00359 astarnode *cnode=m_currentnode;
00360 while(cnode)
00361 {
00362 path.push_back(cnode->m_node);
00363 cnode=cnode->m_parent;
00364 }
00365 }
00366
00367 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00368 void AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::InitializeStep(const NODETYPE &start, const NODETYPE &goal, DESTCOST &destinationcost, GETNEIGHBORS &getneighbors)
00369 {
00370 m_start=&start;
00371 m_goal=&goal;
00372 m_destinationcost=&destinationcost;
00373 m_getneighbors=&getneighbors;
00374
00375
00376 ClearOpenList();
00377 ClearClosedList();
00378 m_helperlist.clear();
00379
00380 m_astaropen=0;
00381 m_currentnode=0;
00382
00383 astarnode *newnode=m_astarnodeallocator.allocate(1);
00384 newnode->m_node=start;
00385 newnode->m_parent=NULL;
00386 newnode->m_g=destinationcost(start,goal);
00387 newnode->m_h=0;
00388 newnode->m_f=newnode->m_g+newnode->m_h;
00389
00390
00391 m_openlist.push_back(newnode);
00392 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00393 m_helperlist[newnode->m_node].m_node=newnode;
00394 m_helperlist[newnode->m_node].m_onopen=true;
00395
00396 }
00397
00398 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00399 const PathResult AStarGeneric<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::Step()
00400 {
00401 if(m_openlist.size()>0)
00402 {
00403 m_currentnode=m_openlist.front();
00404 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00405 m_openlist.pop_back();
00406 m_helperlist[m_currentnode->m_node].m_onopen=false;
00407
00408
00409 m_closedlist.push_back(m_currentnode);
00410 m_helperlist[m_currentnode->m_node].m_onclosed=true;
00411
00412 if(m_currentnode->m_node!=*m_goal)
00413 {
00414 m_getneighbors->operator()(m_currentnode->m_node,AddNeighborFunctor(*this));
00415 }
00416 else
00417 {
00418 return PATH_FOUND;
00419 }
00420
00421 return PATH_SEARCHING;
00422
00423 }
00424
00425 return PATH_NOTFOUND;
00426 }
00427
00428 }
00429
00430 #endif // _pathfinder_astar_generic_