00001 #ifndef _pathfinder_astar_tile8dir_cached_
00002 #define _pathfinder_astar_tile8dir_cached_
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 MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE=double>
00052 class AStarTile8DirCached
00053 {
00054 public:
00055 AStarTile8DirCached();
00056 ~AStarTile8DirCached();
00057
00071 const PathResult FindPath(const std::pair<long,long> &start, const std::pair<long,long> &goal, std::vector<std::pair<long,long> > &finalpath, MOVECOST &movecost, DESTCOST &destinationcost);
00086 const PathResult FindPath(const std::pair<long,long> &start, const std::pair<long,long> &goal, std::vector<std::pair<long,long> > &finalpath, MOVECOST &movecost, MOVEBLOCKED &moveblocked, DESTCOST &destinationcost);
00087
00095 void SetMapWidth(const long width);
00096
00100 void ClearCache();
00101
00109 void ClearCachePosition(const std::pair<long,long> &pos);
00110
00111 private:
00112
00113 AStarTile8DirCached(const AStarTile8DirCached &rhs);
00114 AStarTile8DirCached &operator=(const AStarTile8DirCached &rhs);
00115
00116 struct astarnode
00117 {
00118 std::pair<long,long> m_node;
00119 astarnode *m_parent;
00120 COSTTYPE m_f;
00121 COSTTYPE m_g;
00122 COSTTYPE m_h;
00123 };
00124
00125 struct astarnodecompare:public std::binary_function<astarnode *, astarnode *, bool>
00126 {
00127 inline bool operator()(const astarnode *left, const astarnode *right)
00128 {
00129 return right->m_f<left->m_f;
00130 }
00131 };
00132
00133 class astarallocator:public std::allocator<astarnode>
00134 {
00135 public:
00136 astarallocator()
00137 {
00138 m_mempos=0;
00139 m_mem.resize(1000,NULL);
00140 }
00141
00142 ~astarallocator()
00143 {
00144 for(std::vector<astarnode *>::size_type i=0; i<m_mempos; i++)
00145 {
00146 delete m_mem[i];
00147 }
00148 }
00149
00150 pointer allocate(size_type count)
00151 {
00152 return m_mempos>0 ? m_mem[--m_mempos] : new astarnode;
00153 }
00154
00155 void deallocate(pointer ptr, size_type count)
00156 {
00157 if(m_mempos==m_mem.size())
00158 {
00159 m_mem.resize(m_mem.size()+1000,NULL);
00160 }
00161 m_mem[m_mempos++]=ptr;
00162 }
00163
00164 private:
00165 std::vector<astarnode *> m_mem;
00166 typename std::vector<astarnode *>::size_type m_mempos;
00167 };
00168
00169 struct listelement
00170 {
00171 listelement():m_node(NULL),m_onopen(false),m_onclosed(false) {}
00172 astarnode *m_node;
00173 bool m_onopen;
00174 bool m_onclosed;
00175 };
00176
00177 void ClearOpenList();
00178 void ClearClosedList();
00179
00180 astarallocator m_astarnodeallocator;
00181
00182 std::vector<astarnode *> m_openlist;
00183 std::vector<astarnode *> m_closedlist;
00184 std::vector<listelement> m_helperlist;
00185 long m_helperliststartindex;
00186
00187 long m_mapwidth;
00188
00189 struct cacheelement
00190 {
00191 cacheelement():m_hascache(false) {}
00192 bool m_hascache;
00193 std::vector<std::pair<std::pair<long,long> ,COSTTYPE> > m_neighbors;
00194 };
00195 std::vector<cacheelement> m_cache;
00196 long m_cachestartindex;
00197
00198 inline listelement &hl(const long index)
00199 {
00200 if(m_helperlist.size()==0)
00201 {
00202 m_helperlist.push_back(listelement());
00203 m_helperliststartindex=index;
00204 }
00205 else if(index<m_helperliststartindex)
00206 {
00207 m_helperlist.insert(m_helperlist.begin(),m_helperliststartindex-index,listelement());
00208 m_helperliststartindex=index;
00209 }
00210 else if(index-m_helperliststartindex>=m_helperlist.size())
00211 {
00212 m_helperlist.insert(m_helperlist.end(),((index-m_helperliststartindex)+1)-m_helperlist.size(),listelement());
00213 }
00214
00215 return m_helperlist[index-m_helperliststartindex];
00216 }
00217
00218 };
00219
00220 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00221 AStarTile8DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::AStarTile8DirCached():m_mapwidth(0),m_cachestartindex(0),m_helperliststartindex(0)
00222 {
00223
00224 }
00225
00226 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00227 AStarTile8DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::~AStarTile8DirCached()
00228 {
00229 ClearOpenList();
00230 ClearClosedList();
00231 }
00232
00233 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00234 void AStarTile8DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearCache()
00235 {
00236 m_cache.clear();
00237 m_cachestartindex=0;
00238 }
00239
00240 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00241 void AStarTile8DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearCachePosition(const std::pair<long,long> &pos)
00242 {
00243 long index=(pos.second*m_mapwidth)+pos.first;
00244 if(index>=m_cachestartindex && index-m_cachestartindex<m_cache.size())
00245 {
00246 m_cache[index-m_cachestartindex].m_hascache=false;
00247 m_cache[index-m_cachestartindex].m_neighbors.clear();
00248 }
00249 }
00250
00251 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00252 void AStarTile8DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearClosedList()
00253 {
00254 for(std::vector<astarnode *>::iterator i=m_closedlist.begin(); i!=m_closedlist.end(); i++)
00255 {
00256 m_astarnodeallocator.deallocate((*i),1);
00257 }
00258 m_closedlist.clear();
00259 }
00260
00261 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00262 void AStarTile8DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearOpenList()
00263 {
00264 for(std::vector<astarnode *>::iterator i=m_openlist.begin(); i!=m_openlist.end(); i++)
00265 {
00266 m_astarnodeallocator.deallocate((*i),1);
00267 }
00268 m_openlist.clear();
00269 }
00270
00271 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00272 const PathResult AStarTile8DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::FindPath(const std::pair<long,long> &start, const std::pair<long,long> &goal, std::vector<std::pair<long,long> > &finalpath, MOVECOST &movecost, DESTCOST &destinationcost)
00273 {
00274
00275 ClearOpenList();
00276 ClearClosedList();
00277 m_helperlist.clear();
00278 m_helperliststartindex=0;
00279
00280 long xx;
00281 long yy;
00282
00283 astarnode *astaropen;
00284
00285
00286 astarnode *currentnode;
00287 astarnode *newnode=m_astarnodeallocator.allocate(1);
00288 newnode->m_node=start;
00289 newnode->m_parent=NULL;
00290 newnode->m_g=destinationcost(start,goal);
00291 newnode->m_h=0;
00292 newnode->m_f=newnode->m_g+newnode->m_h;
00293
00294
00295 m_openlist.push_back(newnode);
00296 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00297 hl((newnode->m_node.second*m_mapwidth)+newnode->m_node.first).m_node=newnode;
00298 m_helperlist[((newnode->m_node.second*m_mapwidth)+newnode->m_node.first)-m_helperliststartindex].m_onopen=true;
00299
00300 while(m_openlist.size()>0)
00301 {
00302 currentnode=m_openlist.front();
00303 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00304 m_openlist.pop_back();
00305 m_helperlist[((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first)-m_helperliststartindex].m_onopen=false;
00306
00307
00308 m_closedlist.push_back(currentnode);
00309 m_helperlist[((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first)-m_helperliststartindex].m_onclosed=true;
00310
00311 if(currentnode->m_node!=goal)
00312 {
00313 long currentnodeindex=((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first);
00314 if(currentnodeindex>=m_cachestartindex && currentnodeindex<m_cachestartindex+m_cache.size() && m_cache[currentnodeindex-m_cachestartindex].m_hascache)
00315 {
00316
00317 for(std::vector<std::pair<std::pair<long,long> ,COSTTYPE> >::iterator i=m_cache[currentnodeindex-m_cachestartindex].m_neighbors.begin(); i!=m_cache[currentnodeindex-m_cachestartindex].m_neighbors.end(); i++)
00318 {
00319 xx=(*i).first.first;
00320 yy=(*i).first.second;
00321 if(hl((yy*m_mapwidth)+xx).m_onclosed==false)
00322 {
00323
00324
00325 astaropen=m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node;
00326
00327
00328 if(astaropen!=NULL)
00329 {
00330 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00331 {
00332 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00333 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00334 astaropen->m_parent=currentnode;
00335 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00336 }
00337 }
00338
00339 else
00340 {
00341 newnode=m_astarnodeallocator.allocate(1);
00342 newnode->m_node=std::pair<long,long>(xx,yy);
00343 newnode->m_parent=currentnode;
00344 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00345 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00346 newnode->m_f=newnode->m_g+newnode->m_h;
00347
00348 m_openlist.push_back(newnode);
00349 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00350 hl((yy*m_mapwidth)+xx).m_onopen=true;
00351 m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node=newnode;
00352 }
00353 }
00354 }
00355 }
00356
00357 else
00358 {
00359
00360 if(m_cache.size()==0)
00361 {
00362 m_cache.push_back(cacheelement());
00363 m_cachestartindex=currentnodeindex;
00364 }
00365 else if(currentnodeindex<m_cachestartindex)
00366 {
00367 m_cache.insert(m_cache.begin(),m_cachestartindex-currentnodeindex,cacheelement());
00368 m_cachestartindex=currentnodeindex;
00369 }
00370 else if(currentnodeindex-m_cachestartindex>=m_cache.size())
00371 {
00372 m_cache.insert(m_cache.end(),((currentnodeindex-m_cachestartindex)+1)-m_cache.size(),cacheelement());
00373 }
00374 m_cache[currentnodeindex-m_cachestartindex].m_hascache=true;
00375
00376 for(yy=currentnode->m_node.second-1; yy<=currentnode->m_node.second+1; yy++)
00377 {
00378 for(xx=currentnode->m_node.first-1; xx<=currentnode->m_node.first+1; xx++)
00379 {
00380 if(xx!=currentnode->m_node.first || yy!=currentnode->m_node.second)
00381 {
00382
00383
00384 if(hl((yy*m_mapwidth)+xx).m_onclosed==false)
00385 {
00386
00387
00388 astaropen=m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node;
00389
00390
00391 if(astaropen!=NULL)
00392 {
00393 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00394 {
00395 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00396 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00397 astaropen->m_parent=currentnode;
00398 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00399 }
00400 }
00401
00402 else
00403 {
00404 newnode=m_astarnodeallocator.allocate(1);
00405 newnode->m_node=std::pair<long,long>(xx,yy);
00406 newnode->m_parent=currentnode;
00407 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00408 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00409 newnode->m_f=newnode->m_g+newnode->m_h;
00410
00411 m_openlist.push_back(newnode);
00412 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00413 hl((yy*m_mapwidth)+xx).m_onopen=true;
00414 m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node=newnode;
00415 }
00416
00417 m_cache[currentnodeindex-m_cachestartindex].m_neighbors.push_back(std::pair<std::pair<long,long> ,COSTTYPE>(std::pair<long,long>(xx,yy),movecost(currentnode->m_node,std::pair<long,long>(xx,yy))));
00418
00419 }
00420 }
00421 }
00422 }
00423 }
00424 }
00425 else
00426 {
00427 finalpath.clear();
00428 while(currentnode)
00429 {
00430 finalpath.push_back(currentnode->m_node);
00431 currentnode=currentnode->m_parent;
00432 }
00433 return PATH_FOUND;
00434 }
00435
00436 }
00437
00438 return PATH_NOTFOUND;
00439 }
00440
00441 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00442 const PathResult AStarTile8DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::FindPath(const std::pair<long,long> &start, const std::pair<long,long> &goal, std::vector<std::pair<long,long> > &finalpath, MOVECOST &movecost, MOVEBLOCKED &moveblocked, DESTCOST &destinationcost)
00443 {
00444
00445 ClearOpenList();
00446 ClearClosedList();
00447 m_helperlist.clear();
00448 m_helperliststartindex=0;
00449
00450 long xx;
00451 long yy;
00452
00453 astarnode *astaropen;
00454
00455
00456 astarnode *currentnode;
00457 astarnode *newnode=m_astarnodeallocator.allocate(1);
00458 newnode->m_node=start;
00459 newnode->m_parent=NULL;
00460 newnode->m_g=destinationcost(start,goal);
00461 newnode->m_h=0;
00462 newnode->m_f=newnode->m_g+newnode->m_h;
00463
00464
00465 m_openlist.push_back(newnode);
00466 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00467 m_helperlist[newnode->m_node].m_node=newnode;
00468 m_helperlist[newnode->m_node].m_onopen=true;
00469
00470 while(m_openlist.size()>0)
00471 {
00472 currentnode=m_openlist.front();
00473 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00474 m_openlist.pop_back();
00475 m_helperlist[currentnode->m_node].m_onopen=false;
00476
00477
00478 m_closedlist.push_back(currentnode);
00479 m_helperlist[currentnode->m_node].m_onclosed=true;
00480
00481 if(currentnode->m_node!=goal)
00482 {
00483
00484 long currentnodeindex=((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first);
00485 if(currentnodeindex>=m_cachestartindex && currentnodeindex<m_cachestartindex+m_cache.size() && m_cache[currentnodeindex-m_cachestartindex].m_hascache)
00486 {
00487
00488 for(std::vector<std::pair<std::pair<long,long> ,COSTTYPE> >::iterator i=m_cache[currentnodeindex-m_cachestartindex].m_neighbors.begin(); i!=m_cache[currentnodeindex-m_cachestartindex].m_neighbors.end(); i++)
00489 {
00490 xx=(*i).first.first;
00491 yy=(*i).first.second;
00492 if(hl((yy*m_mapwidth)+xx).m_onclosed==false)
00493 {
00494
00495
00496 astaropen=m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node;
00497
00498
00499 if(astaropen!=NULL)
00500 {
00501 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00502 {
00503 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00504 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00505 astaropen->m_parent=currentnode;
00506 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00507 }
00508 }
00509
00510 else
00511 {
00512 newnode=m_astarnodeallocator.allocate(1);
00513 newnode->m_node=std::pair<long,long>(xx,yy);
00514 newnode->m_parent=currentnode;
00515 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00516 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00517 newnode->m_f=newnode->m_g+newnode->m_h;
00518
00519 m_openlist.push_back(newnode);
00520 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00521 hl((yy*m_mapwidth)+xx).m_onopen=true;
00522 m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node=newnode;
00523 }
00524 }
00525 }
00526 }
00527
00528 else
00529 {
00530
00531 if(m_cache.size()==0)
00532 {
00533 m_cache.push_back(cacheelement());
00534 m_cachestartindex=currentnodeindex;
00535 }
00536 else if(currentnodeindex<m_cachestartindex)
00537 {
00538 m_cache.insert(m_cache.begin(),m_cachestartindex-currentnodeindex,cacheelement());
00539 m_cachestartindex=currentnodeindex;
00540 }
00541 else if(currentnodeindex-m_cachestartindex>=m_cache.size())
00542 {
00543 m_cache.insert(m_cache.end(),((currentnodeindex-m_cachestartindex)+1)-m_cache.size(),cacheelement());
00544 }
00545
00546 for(yy=currentnode->m_node.second-1; yy<=currentnode->m_node.second+1; yy++)
00547 {
00548 for(xx=currentnode->m_node.first-1; xx<=currentnode->m_node.first+1; xx++)
00549 {
00550 if(xx!=currentnode->m_node.first || yy!=currentnode->m_node.second)
00551 {
00552
00553
00554 if(moveblocked(currentnode->m_node,std::pair<long,long>(xx,yy))==false && hl((yy*m_mapwidth)+xx).m_onclosed==false)
00555 {
00556
00557
00558 astaropen=m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node;
00559
00560
00561 if(astaropen!=NULL)
00562 {
00563 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00564 {
00565 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00566 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00567 astaropen->m_parent=currentnode;
00568 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00569 }
00570 }
00571
00572 else
00573 {
00574 newnode=m_astarnodeallocator.allocate(1);
00575 newnode->m_node=std::pair<long,long>(xx,yy);
00576 newnode->m_parent=currentnode;
00577 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00578 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00579 newnode->m_f=newnode->m_g+newnode->m_h;
00580
00581 m_openlist.push_back(newnode);
00582 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00583 hl((yy*m_mapwidth)+xx).m_onopen=true;
00584 m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node=newnode;
00585 }
00586
00587 m_cache[currentnodeindex-m_cachestartindex].m_hascache=true;
00588 m_cache[currentnodeindex-m_cachestartindex].m_neighbors.push_back(std::pair<std::pair<long,long> ,COSTTYPE>(std::pair<long,long>(xx,yy),movecost(currentnode->m_node,std::pair<long,long>(xx,yy))));
00589
00590 }
00591 }
00592 }
00593 }
00594 }
00595 }
00596 else
00597 {
00598 finalpath.clear();
00599 while(currentnode)
00600 {
00601 finalpath.push_back(currentnode->m_node);
00602 currentnode=currentnode->m_parent;
00603 }
00604 return PATH_FOUND;
00605 }
00606
00607 }
00608
00609 return PATH_NOTFOUND;
00610 }
00611
00612 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00613 void AStarTile8DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::SetMapWidth(const long width)
00614 {
00615 if(width!=m_mapwidth)
00616 {
00617 m_mapwidth=width;
00618 ClearCache();
00619 }
00620 }
00621
00622 }
00623
00624 #endif // _pathfinder_astar_tile8dir_