00001 #ifndef _pathfinder_astar_tile8dir_
00002 #define _pathfinder_astar_tile8dir_
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 AStarTile8Dir
00053 {
00054 public:
00055 AStarTile8Dir();
00056 ~AStarTile8Dir();
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
00088 private:
00089
00090 AStarTile8Dir(const AStarTile8Dir &rhs);
00091 AStarTile8Dir &operator=(const AStarTile8Dir &rhs);
00092
00093 struct astarnode
00094 {
00095 std::pair<long,long> m_node;
00096 astarnode *m_parent;
00097 COSTTYPE m_f;
00098 COSTTYPE m_g;
00099 COSTTYPE m_h;
00100 };
00101
00102 struct astarnodecompare:public std::binary_function<astarnode *, astarnode *, bool>
00103 {
00104 inline bool operator()(const astarnode *left, const astarnode *right)
00105 {
00106 return right->m_f<left->m_f;
00107 }
00108 };
00109
00110 class astarallocator:public std::allocator<astarnode>
00111 {
00112 public:
00113 astarallocator()
00114 {
00115 m_mempos=0;
00116 m_mem.resize(1000,NULL);
00117 }
00118
00119 ~astarallocator()
00120 {
00121 for(std::vector<astarnode *>::size_type i=0; i<m_mempos; i++)
00122 {
00123 delete m_mem[i];
00124 }
00125 }
00126
00127 pointer allocate(size_type count)
00128 {
00129 return m_mempos>0 ? m_mem[--m_mempos] : new astarnode;
00130 }
00131
00132 void deallocate(pointer ptr, size_type count)
00133 {
00134 if(m_mempos==m_mem.size())
00135 {
00136 m_mem.resize(m_mem.size()+1000,NULL);
00137 }
00138 m_mem[m_mempos++]=ptr;
00139 }
00140
00141 private:
00142 std::vector<astarnode *> m_mem;
00143 typename std::vector<astarnode *>::size_type m_mempos;
00144 };
00145
00146 struct listelement
00147 {
00148 listelement():m_node(NULL),m_onopen(false),m_onclosed(false) {}
00149 astarnode *m_node;
00150 bool m_onopen;
00151 bool m_onclosed;
00152 };
00153
00154 void ClearOpenList();
00155 void ClearClosedList();
00156
00157 astarallocator m_astarnodeallocator;
00158
00159 std::vector<astarnode *> m_openlist;
00160 std::vector<astarnode *> m_closedlist;
00161 std::map<std::pair<long,long>, listelement> m_helperlist;
00162
00163 };
00164
00165 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00166 AStarTile8Dir<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::AStarTile8Dir()
00167 {
00168
00169 }
00170
00171 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00172 AStarTile8Dir<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::~AStarTile8Dir()
00173 {
00174 ClearOpenList();
00175 ClearClosedList();
00176 }
00177
00178 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00179 void AStarTile8Dir<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearClosedList()
00180 {
00181 for(std::vector<astarnode *>::iterator i=m_closedlist.begin(); i!=m_closedlist.end(); i++)
00182 {
00183 m_astarnodeallocator.deallocate((*i),1);
00184 }
00185 m_closedlist.clear();
00186 }
00187
00188 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00189 void AStarTile8Dir<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearOpenList()
00190 {
00191 for(std::vector<astarnode *>::iterator i=m_openlist.begin(); i!=m_openlist.end(); i++)
00192 {
00193 m_astarnodeallocator.deallocate((*i),1);
00194 }
00195 m_openlist.clear();
00196 }
00197
00198 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00199 const PathResult AStarTile8Dir<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)
00200 {
00201
00202 ClearOpenList();
00203 ClearClosedList();
00204 m_helperlist.clear();
00205
00206 long xx;
00207 long yy;
00208
00209 astarnode *astaropen;
00210
00211
00212 astarnode *currentnode;
00213 astarnode *newnode=m_astarnodeallocator.allocate(1);
00214 newnode->m_node=start;
00215 newnode->m_parent=NULL;
00216 newnode->m_g=destinationcost(start,goal);
00217 newnode->m_h=0;
00218 newnode->m_f=newnode->m_g+newnode->m_h;
00219
00220
00221 m_openlist.push_back(newnode);
00222 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00223 m_helperlist[newnode->m_node].m_node=newnode;
00224 m_helperlist[newnode->m_node].m_onopen=true;
00225
00226 while(m_openlist.size()>0)
00227 {
00228 currentnode=m_openlist.front();
00229 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00230 m_openlist.pop_back();
00231 m_helperlist[currentnode->m_node].m_onopen=false;
00232
00233
00234 m_closedlist.push_back(currentnode);
00235 m_helperlist[currentnode->m_node].m_onclosed=true;
00236
00237 if(currentnode->m_node!=goal)
00238 {
00239
00240 for(yy=currentnode->m_node.second-1; yy<=currentnode->m_node.second+1; yy++)
00241 {
00242 for(xx=currentnode->m_node.first-1; xx<=currentnode->m_node.first+1; xx++)
00243 {
00244 if(xx!=currentnode->m_node.first || yy!=currentnode->m_node.second)
00245 {
00246
00247
00248 if(m_helperlist[std::pair<long,long>(xx,yy)].m_onclosed==false)
00249 {
00250
00251
00252 astaropen=m_helperlist[std::pair<long,long>(xx,yy)].m_node;
00253
00254
00255 if(astaropen!=NULL)
00256 {
00257 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00258 {
00259 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00260 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00261 astaropen->m_parent=currentnode;
00262 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00263 }
00264 }
00265
00266 else
00267 {
00268 newnode=m_astarnodeallocator.allocate(1);
00269 newnode->m_node=std::pair<long,long>(xx,yy);
00270 newnode->m_parent=currentnode;
00271 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00272 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00273 newnode->m_f=newnode->m_g+newnode->m_h;
00274
00275 m_openlist.push_back(newnode);
00276 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00277 m_helperlist[newnode->m_node].m_onopen=true;
00278 m_helperlist[newnode->m_node].m_node=newnode;
00279 }
00280
00281 }
00282 }
00283 }
00284 }
00285 }
00286 else
00287 {
00288 finalpath.clear();
00289 while(currentnode)
00290 {
00291 finalpath.push_back(currentnode->m_node);
00292 currentnode=currentnode->m_parent;
00293 }
00294 return PATH_FOUND;
00295 }
00296
00297 }
00298
00299 return PATH_NOTFOUND;
00300 }
00301
00302 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00303 const PathResult AStarTile8Dir<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)
00304 {
00305
00306 ClearOpenList();
00307 ClearClosedList();
00308 m_helperlist.clear();
00309
00310 long xx;
00311 long yy;
00312
00313 astarnode *astaropen;
00314
00315
00316 astarnode *currentnode;
00317 astarnode *newnode=m_astarnodeallocator.allocate(1);
00318 newnode->m_node=start;
00319 newnode->m_parent=NULL;
00320 newnode->m_g=destinationcost(start,goal);
00321 newnode->m_h=0;
00322 newnode->m_f=newnode->m_g+newnode->m_h;
00323
00324
00325 m_openlist.push_back(newnode);
00326 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00327 m_helperlist[newnode->m_node].m_node=newnode;
00328 m_helperlist[newnode->m_node].m_onopen=true;
00329
00330 while(m_openlist.size()>0)
00331 {
00332 currentnode=m_openlist.front();
00333 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00334 m_openlist.pop_back();
00335 m_helperlist[currentnode->m_node].m_onopen=false;
00336
00337
00338 m_closedlist.push_back(currentnode);
00339 m_helperlist[currentnode->m_node].m_onclosed=true;
00340
00341 if(currentnode->m_node!=goal)
00342 {
00343
00344 for(yy=currentnode->m_node.second-1; yy<=currentnode->m_node.second+1; yy++)
00345 {
00346 for(xx=currentnode->m_node.first-1; xx<=currentnode->m_node.first+1; xx++)
00347 {
00348 if(xx!=currentnode->m_node.first || yy!=currentnode->m_node.second)
00349 {
00350
00351
00352 if(moveblocked(currentnode->m_node,std::pair<long,long>(xx,yy))==false && m_helperlist[std::pair<long,long>(xx,yy)].m_onclosed==false)
00353 {
00354
00355
00356 astaropen=m_helperlist[std::pair<long,long>(xx,yy)].m_node;
00357
00358
00359 if(astaropen!=NULL)
00360 {
00361 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00362 {
00363 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00364 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00365 astaropen->m_parent=currentnode;
00366 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00367 }
00368 }
00369
00370 else
00371 {
00372 newnode=m_astarnodeallocator.allocate(1);
00373 newnode->m_node=std::pair<long,long>(xx,yy);
00374 newnode->m_parent=currentnode;
00375 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00376 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00377 newnode->m_f=newnode->m_g+newnode->m_h;
00378
00379 m_openlist.push_back(newnode);
00380 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00381 m_helperlist[newnode->m_node].m_onopen=true;
00382 m_helperlist[newnode->m_node].m_node=newnode;
00383 }
00384
00385 }
00386 }
00387 }
00388 }
00389 }
00390 else
00391 {
00392 finalpath.clear();
00393 while(currentnode)
00394 {
00395 finalpath.push_back(currentnode->m_node);
00396 currentnode=currentnode->m_parent;
00397 }
00398 return PATH_FOUND;
00399 }
00400
00401 }
00402
00403 return PATH_NOTFOUND;
00404 }
00405
00406 }
00407
00408 #endif // _pathfinder_astar_tile8dir_