AI_AStar.h

Go to the documentation of this file.
00001 #ifndef AI_A_STAR_H
00002 #define AI_A_STAR_H
00003 
00004 #include "AI_Global.h"
00005 #include "utils/AI_Array.h"
00006 
00007 
00008 #define GRAPH_INITIAL_SIZE 0
00009 #define GRAPH_GROW_SIZE 8
00010 
00011 
00033 class AI_AStar
00034 {
00035 //*** Embedded
00036 public:
00037     class Link;
00038     class Node;
00039     class Graph;
00040     class Session;
00041 
00043     typedef AI_Array<Link*> LinkArray;
00045     typedef LinkArray::iterator LinkArrayIt;
00047     typedef AI_Array<Node*> NodeArray;
00049     typedef NodeArray::iterator NodeArrayIt;
00050 
00054     class Node {
00055     //*** Attributes
00056     protected:
00058         int m_i_index;
00060         LinkArray m_arr_links;
00062         void *m_ptr_user_data;
00063 
00064     //*** Methods
00065     public:
00066         Node ();
00067 
00068         //*** Building
00069         void removeLink ( Link *ptr_link );
00070         void addLink( Link *ptr_link );
00071         void reset(void);
00072 
00073         //*** Sets
00074         void set (int i_index);
00075         void setUserData( void *ptr_data );
00076 
00077         //*** Gets
00078         void *getUserData( void ) const;
00079         int getIndex( void ) const;
00080         LinkArray &getLinks( void );
00081 
00082         //*** Utils
00083         Link *isLinkedTo( Node *ptr_other );
00084     };
00085 
00086 
00090     class Link {
00091     //*** Attributes
00092     protected:
00094         Node *m_ptr_node1;
00096         Node *m_ptr_node2;
00098         float m_f_length;
00100         float m_f_min_width;
00102         float m_f_max_width;
00104         void *m_ptr_user_data;
00106         Session *m_ptr_session;
00107 
00108     //*** Methods
00109     public:
00110         //*** Constructors & destructors
00111         Link();
00112 
00113         //*** Sets
00114         void set( Node *ptr_node1, Node *ptr_node2, float f_length, float f_min, float f_max, Session *ptr_session=NULL );
00115         void setUserData( void *ptr_data );
00116 
00117         //*** Gets
00118         void *getUserData( void ) const;
00119         Node *getFirstNode ( void ) const;
00120         Node *getSecondNode ( void ) const;
00121         const float getMinWidth ( void ) const;
00122         const float getMaxWidth ( void ) const;
00123         const float getLength ( void ) const;
00124         Node *getOtherNode ( Node *ptr_node );
00125         Session *getSession( void );
00126 
00127     };
00128 
00129 
00144     class Graph {
00145     protected:
00147         NodeArray m_arr_nodes;
00149         LinkArray m_arr_links;
00151         int m_i_first_node_index;
00152 
00153     public:
00154         //*** Constructor & Destructor
00155         Graph();
00156         ~Graph();
00157 
00158         //*** Building
00159         Node *addNode ( void *ptr_user_data = NULL );
00160         Link *addLink ( Node *ptr_node1, Node *ptr_node2, float f_lenght, float f_min, float f_max, Session *ptr_session=NULL );
00161         void reset( void );
00162         void clear( void );
00163         void setBaseNodeIndex( const int i);
00164         const int getBaseNodeIndex( void ) const;
00165         const int getLinksNumber( void ) const;
00166         const int getNodesNumber( void ) const;
00167         Node *getNode(const int i) const;
00168         Link *getLink(const int i) const;
00169     };
00170 
00171 
00178     class Informator {
00179     public:
00180         virtual float getHeuristic ( Node *ptr_node1, Node *ptr_node2 ) = 0;
00181     };
00182 
00183 
00194     class Session {
00195         friend AI_AStar;
00196 
00197     //*** Embedded
00198     private:
00201         struct PathSegment {
00203             Node *ptr_node_first;
00205             Node *ptr_node_second;
00206         };
00207 
00210         struct PathDirection {
00212             Node *ptr_node;
00214             float f_distance;
00216             float f_guess;
00217 
00218         public:
00219             PathDirection(void);
00220             PathDirection(Node *ptr_node, float f_distance, float f_guess);
00221         };
00222 
00224         typedef AI_Array<PathDirection>::iterator DirectionVectorIt;
00225     
00226     //*** Attributes
00227     private:
00229         Graph m_graph;
00231         float m_f_agent_width;
00233         AI_Array<PathSegment> m_arr_segments;
00235         AI_Array<PathDirection> m_arr_directions;
00237         unsigned char *m_ptr_byte_visited;
00239         int m_i_visited_size;
00241         float m_f_distance;
00243         Node *m_ptr_node_actual;
00245         Node *m_ptr_node_start;
00247         Node *m_ptr_node_final;
00249         NodeArray m_arr_way;
00250 
00251     //*** Methods
00252     protected:
00253         //*** Sets
00254         void setNodeVisited( int i );
00255         void pushDirection( Node *ptr_node, float f_distance, float f_depth );
00256         void pushSegment( Node *ptr_node1, Node *ptr_node2 );
00257         void pushWay( Node *ptr_node );
00258 
00259         //*** Gets
00260         bool isNodeVisited( int i );
00261         Node *getActualNode( void );
00262         float getActualDistance( void );
00263         PathSegment &getBackSegment( void );
00264 
00265         //*** Utils
00266         bool beginSearch ( void );
00267         void endSearch ( void );
00268         bool isFinishReached( void );
00269         bool moveBestDirection( void );
00270         void removeBackSegment( void );
00271     
00272     public:
00273         //*** Constructor & destructor
00274         Session();
00275         ~Session();
00276 
00277         //*** Build subgraph
00278         Node *addNode ( void *ptr_user_data );
00279         Link *addLink ( Node *ptr_node1, Node *ptr_node2, float f_lenght, float f_min, float f_max );
00280         void reset ( AI_AStar *ptr_astar );
00281 
00282         //*** Find way
00283         void setMission ( Node *ptr_node_start, Node *ptr_node_final );
00284         int getWaySize( void );
00285         Node *getWayNode( int i );
00286 
00287         //*** Sets
00288         void setAgentWidth( float f_width );
00289         void setAStar( AI_AStar *ptr_astar );
00290 
00291         //*** Gets
00292         float getAgentWidth( void );
00293         Node *getStartNode( void );
00294         Node *getFinalNode( void );
00295     };
00296 
00297 
00298 //*** Attributes
00299 private:
00301     Informator *m_ptr_informator;
00303     Graph m_graph;
00304     
00305 
00306 //*** Methods
00307 public:
00308     AI_AStar(void);
00309     ~AI_AStar(void);
00310 
00311     //*** Building graph
00312     Node *addNode ( void *ptr_user_data = NULL );
00313     Link *addLink ( Node *ptr_node1, Node *ptr_node2, float f_lenght, float f_min, float f_max );
00314     void clear(void);
00315 
00316     //*** Sets
00317     void setInformator (Informator *ptr_informator);
00318 
00319     //*** Gets
00320     int getLinksNumber( void ) const;
00321     Link *getLink ( int i ) const;
00322     int getNodesNumber( void ) const;
00323     Node *getNode ( int i ) const;
00324 
00325     //*** Find way
00326     bool findWay ( Session &session );
00327 };
00328 
00329 
00332 inline
00333 void AI_AStar::Node::set (int i_index)
00334 {
00335     m_i_index = i_index;
00336 }
00337 
00338 
00341 inline
00342 void AI_AStar::Node::setUserData( void *ptr_data )
00343 {
00344     m_ptr_user_data = ptr_data;
00345 }
00346 
00347 
00350 inline
00351 void *AI_AStar::Node::getUserData( void ) const
00352 {
00353     return m_ptr_user_data;
00354 }
00355 
00356 
00359 inline
00360 void AI_AStar::Link::set(Node *ptr_node1, Node *ptr_node2, float f_length, float f_min, float f_max, Session *ptr_session)
00361 {
00362     m_ptr_user_data = NULL;
00363     m_ptr_node1 = ptr_node1;
00364     m_ptr_node2 = ptr_node2;
00365     m_f_length = f_length;
00366     m_f_min_width = f_min;
00367     m_f_max_width = f_max;
00368     m_ptr_session = ptr_session;
00369 }
00370 
00371 
00374 inline
00375 AI_AStar::Graph::Graph() :
00376     m_arr_nodes(GRAPH_INITIAL_SIZE, GRAPH_GROW_SIZE, NULL),
00377     m_arr_links(GRAPH_INITIAL_SIZE, GRAPH_GROW_SIZE, NULL),
00378     m_i_first_node_index(0)
00379 {
00380     NodeArrayIt it_n = m_arr_nodes.Begin();
00381     for (int i=0; i<m_arr_nodes.AllocSize(); i++, it_n++)
00382         *it_n=NULL;
00383 
00384     LinkArrayIt it_l = m_arr_links.Begin();
00385     for (int i=0; i<m_arr_links.AllocSize(); i++, it_l++)
00386         *it_l=NULL;
00387 }
00388 
00389 
00392 inline
00393 AI_AStar::Graph::~Graph()
00394 {
00395     clear();
00396 }
00397 
00398 
00401 inline
00402 void AI_AStar::Graph::setBaseNodeIndex( const int i)
00403 {
00404     m_i_first_node_index = i;
00405 }
00406 
00407 
00410 inline
00411 const int AI_AStar::Graph::getBaseNodeIndex( void ) const
00412 {
00413     return m_i_first_node_index;
00414 }
00415 
00416 
00419 inline 
00420 const int AI_AStar::Graph::getLinksNumber( void ) const
00421 {
00422     return m_arr_links.Size();
00423 }
00424 
00425 
00428 inline 
00429 const int AI_AStar::Graph::getNodesNumber( void ) const
00430 {
00431     return m_arr_nodes.Size();
00432 }
00433 
00434 
00437 inline 
00438 AI_AStar::Node *AI_AStar::Graph::getNode(const int i) const
00439 {
00440     return m_arr_nodes[i];
00441 }
00442 
00443 
00446 inline 
00447 AI_AStar::Link *AI_AStar::Graph::getLink(const int i) const
00448 {
00449     return m_arr_links[i];
00450 }
00451 
00452 
00453 
00456 inline
00457 AI_AStar::Node::Node () :
00458     m_ptr_user_data(NULL)
00459 {
00460 }
00461 
00462 
00466 inline
00467 AI_AStar::Link *AI_AStar::Node::isLinkedTo( Node *ptr_other )
00468 {
00469     for (LinkArrayIt it=m_arr_links.Begin(); it!=m_arr_links.End(); it++)
00470     {
00471         if ( ptr_other==(*it)->getOtherNode ( this ) )
00472         {
00473             return (*it);
00474         }
00475     }
00476 
00477     return NULL;
00478 }
00479 
00480 
00483 inline
00484 void AI_AStar::Node::removeLink ( Link *ptr_link )
00485 {
00486     //*** Iterate backward to increase chance to find link to
00487     //    be removed first.
00488     if ( m_arr_links.Size()>0 )
00489     {
00490         LinkArrayIt it = m_arr_links.End();
00491         do {
00492             it--;
00493 
00494             if (*it==ptr_link)
00495             {   
00496                 m_arr_links.Erase(it);
00497                 return;
00498             }
00499         } while( it!=m_arr_links.Begin() );
00500     }
00501 }
00502 
00503 
00506 inline
00507 int AI_AStar::Node::getIndex( void ) const
00508 {
00509     return m_i_index;
00510 }
00511 
00512 
00515 inline
00516 AI_AStar::LinkArray &AI_AStar::Node::getLinks( void )
00517 {
00518     return m_arr_links;
00519 }
00520 
00521 
00524 inline
00525 void AI_AStar::Node::addLink( Link *ptr_link )
00526 {
00527     m_arr_links.Append( ptr_link );
00528 }
00529 
00530 
00533 inline
00534 void AI_AStar::Node::reset(void)
00535 {
00536     m_arr_links.Reset();
00537 }
00538 
00539 
00542 inline
00543 AI_AStar::Link::Link() :
00544     m_ptr_session(NULL),
00545     m_ptr_node1(NULL),
00546     m_ptr_node2(NULL),
00547     m_ptr_user_data(NULL)
00548 {
00549 }
00550 
00551 
00554 inline
00555 AI_AStar::Node *AI_AStar::Link::getOtherNode ( Node *ptr_node )
00556 {
00557     if ( m_ptr_node1==ptr_node )
00558         return m_ptr_node2;
00559     
00560     return m_ptr_node1;
00561 }
00562 
00563 
00566 inline
00567 AI_AStar::Node *AI_AStar::Link::getFirstNode ( void ) const
00568 {
00569     return m_ptr_node1;
00570 }
00571 
00572 
00575 inline
00576 AI_AStar::Node *AI_AStar::Link::getSecondNode ( void ) const
00577 {
00578     return m_ptr_node2;
00579 }
00580 
00581 
00584 inline
00585 AI_AStar::Session *AI_AStar::Link::getSession( void )
00586 {
00587     return m_ptr_session;
00588 }
00589 
00590 
00593 inline
00594 const float AI_AStar::Link::getMinWidth ( void ) const
00595 {
00596     return m_f_min_width;
00597 }
00598 
00599 
00602 inline
00603 const float AI_AStar::Link::getMaxWidth ( void ) const
00604 {
00605     return m_f_max_width;
00606 }
00607 
00608 
00611 inline
00612 const float AI_AStar::Link::getLength ( void ) const
00613 {
00614     return m_f_length;
00615 }
00616 
00617 
00620 inline
00621 void *AI_AStar::Link::getUserData( void ) const
00622 {
00623     return m_ptr_session;
00624 }
00625 
00626 
00629 inline
00630 AI_AStar::Session::Session() :
00631     m_ptr_byte_visited(NULL),
00632     m_i_visited_size(0),
00633     m_f_agent_width(0)
00634 {
00635 }
00636 
00637 
00640 inline
00641 AI_AStar::Session::~Session()
00642 {
00643     m_graph.reset();
00644 
00645     if (m_ptr_byte_visited)
00646     {
00647         delete(m_ptr_byte_visited);
00648     }
00649 }
00650 
00651 
00654 inline
00655 AI_AStar::Node *AI_AStar::Session::addNode ( void *ptr_user_data )
00656 {
00657     return m_graph.addNode( ptr_user_data );
00658 }
00659 
00660 
00669 inline
00670 AI_AStar::Link *AI_AStar::Session::addLink ( Node *ptr_node1, Node *ptr_node2, float f_lenght, float f_min, float f_max)
00671 {
00672     return m_graph.addLink( ptr_node1, ptr_node2, f_lenght, f_min, f_max, this );
00673 }
00674 
00675 
00678 inline
00679 bool AI_AStar::Session::isFinishReached( void )
00680 {
00681     return (m_ptr_node_actual==m_ptr_node_final);
00682 }
00683 
00684 
00687 inline
00688 bool AI_AStar::Session::isNodeVisited( int i )
00689 {
00690     unsigned char c = m_ptr_byte_visited[ i / 8 ];
00691     if (c & 1<<(i%8))
00692     {
00693         return true;
00694     }
00695     return false;
00696 }
00697 
00698 
00701 inline
00702 void AI_AStar::Session::setNodeVisited( int i )
00703 {
00704     unsigned char &c = m_ptr_byte_visited[ i / 8 ];
00705     c |= 1<<(i%8);
00706 }
00707 
00708 
00711 inline
00712 void AI_AStar::Session::setAgentWidth( float f_width )
00713 {
00714     m_f_agent_width = f_width;
00715 }
00716 
00717 
00720 inline
00721 float AI_AStar::Session::getAgentWidth( void )
00722 {
00723     return m_f_agent_width;
00724 }
00725 
00726 
00729 inline
00730 AI_AStar::Node *AI_AStar::Session::getActualNode( void )
00731 {
00732     return m_ptr_node_actual;
00733 }
00734 
00735 
00738 inline
00739 float AI_AStar::Session::getActualDistance( void )
00740 {
00741     return m_f_distance;
00742 }
00743 
00744 
00747 inline
00748 void AI_AStar::Session::pushDirection( Node *ptr_node, float f_distance, float f_guess )
00749 {
00750     PathDirection &dir = m_arr_directions.PushBack();
00751 
00752     dir.ptr_node = ptr_node;
00753     dir.f_distance = f_distance;
00754     dir.f_guess = f_guess;
00755 }
00756 
00757 
00760 inline
00761 void AI_AStar::Session::pushSegment( Node *ptr_node1, Node *ptr_node2 )
00762 {
00763     PathSegment &segment = m_arr_segments.PushBack();
00764 
00765     segment.ptr_node_first = ptr_node1;
00766     segment.ptr_node_second = ptr_node2;
00767 }
00768 
00769 
00772 inline
00773 AI_AStar::Node *AI_AStar::Session::getStartNode( void )
00774 {
00775     return m_ptr_node_start;
00776 }
00777 
00778 
00781 inline
00782 AI_AStar::Node *AI_AStar::Session::getFinalNode( void )
00783 {
00784     return m_ptr_node_final;
00785 }
00786 
00787 
00790 inline
00791 AI_AStar::Session::PathSegment &AI_AStar::Session::getBackSegment( void )
00792 {
00793     return m_arr_segments.Back();
00794 }
00795 
00796 
00799 inline
00800 void AI_AStar::Session::removeBackSegment( void )
00801 {
00802     m_arr_segments.PopBack();
00803 }
00804 
00805 
00808 inline
00809 void AI_AStar::Session::pushWay( Node *ptr_node )
00810 {
00811     m_arr_way.PushBack( ptr_node );
00812 }
00813 
00814 
00817 inline
00818 int AI_AStar::Session::getWaySize( void )
00819 {
00820     return m_arr_way.Size();
00821 }
00822 
00823 
00826 inline
00827 AI_AStar::Node *AI_AStar::Session::getWayNode( int i )
00828 {
00829     return m_arr_way[getWaySize()-i-1];
00830 }
00831 
00832 
00835 inline
00836 void AI_AStar::Session::setMission ( Node *ptr_node_start, Node *ptr_node_final )
00837 {
00838     m_ptr_node_start = ptr_node_start;
00839     m_ptr_node_final = ptr_node_final;
00840 }
00841 
00842 
00846 inline
00847 void AI_AStar::Session::reset ( AI_AStar *ptr_astar )
00848 {
00849     m_graph.reset();
00850     m_graph.setBaseNodeIndex( ptr_astar->getNodesNumber() );
00851 }
00852 
00853 
00856 inline
00857 AI_AStar::Session::PathDirection::PathDirection(void) :
00858     ptr_node(NULL)
00859 {
00860 }
00861 
00862 
00865 inline
00866 AI_AStar::Session::PathDirection::PathDirection(Node *ptr_node, float f_distance, float f_guess) :
00867     ptr_node(ptr_node),
00868     f_distance(f_distance),
00869     f_guess(f_guess)
00870 {
00871 }
00872 
00873 
00876 inline
00877 AI_AStar::AI_AStar(void) : 
00878     m_ptr_informator(NULL)
00879 {
00880 }
00881 
00882 
00885 inline
00886 AI_AStar::~AI_AStar(void)
00887 {
00888 }
00889 
00890 
00895 inline
00896 void AI_AStar::clear(void)
00897 {
00898     m_graph.clear();
00899 }
00900 
00901 
00904 inline
00905 AI_AStar::Node *AI_AStar::addNode ( void *ptr_user_data )
00906 {
00907     return m_graph.addNode( ptr_user_data );
00908 }
00909 
00910 
00919 inline
00920 AI_AStar::Link *AI_AStar::addLink ( Node *ptr_node1, Node *ptr_node2, float f_lenght, float f_min, float f_max)
00921 {
00922     return m_graph.addLink(ptr_node1, ptr_node2, f_lenght, f_min, f_max);
00923 }
00924 
00925 
00928 inline
00929 int AI_AStar::getLinksNumber( void ) const
00930 {
00931     return m_graph.getLinksNumber();
00932 }
00933 
00934 
00937 inline
00938 AI_AStar::Link *AI_AStar::getLink ( int i ) const
00939 {
00940     return m_graph.getLink(i);
00941 }
00942 
00943 
00946 inline
00947 int AI_AStar::getNodesNumber( void ) const
00948 {
00949     return m_graph.getNodesNumber();
00950 }
00951 
00952 
00955 inline
00956 AI_AStar::Node *AI_AStar::getNode ( int i ) const
00957 {
00958     return m_graph.getNode(i);
00959 }
00960 
00961 
00964 inline
00965 void AI_AStar::setInformator (Informator *ptr_informator)
00966 {
00967     m_ptr_informator = ptr_informator;
00968 }
00969 
00970 
00971 #endif