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