A*寻路算法源码
Astar.h源码
#pragma once
#include "stdafx.h"
#include "MinHeap.h"
class AstarNodeRun;
class Astar;
class AstarRunData;
class AstarNode
{
public:
int nodeIndex;
int connectNum;
AstarNode** connects;
AstarNode(int nodeIndex):connectNum(0),connects(NULL){this->nodeIndex = nodeIndex;}
virtual double getH(AstarNode* target) = 0;
virtual double getCost(int i) = 0;
};
class AstarNodeRun : public MinHeapNode
{
public:
double g;
double h;
AstarNode* node;
AstarNodeRun* parent;
unsigned short pathID;
bool isOpen;
AstarNodeRun():MinHeapNode(0),g(0),h(0),node(NULL),parent(NULL),pathID(0),isOpen(false)
{
}
double f()
{
return g+h;
}
};
class AstarRunData
{
public:
Astar* astar;
unsigned short pathID;
AstarNodeRun** runNodes;
int nodeCount;
MinHeap* openNodesHeap;
AstarRunData(int nodeNum, AstarNode** nodes);
void clearPathId();
void init(Astar* p);
~AstarRunData();
};
class Astar
{
private:
static unsigned short nextPathID;
public:
unsigned short pathID;
AstarRunData* runData;
AstarNode* startNode;
AstarNode* endNode;
int searchedNodes;
Astar();
AstarNodeRun* getNodeRun(int nodeIndex);
void init(AstarRunData* runData, AstarNode* start, AstarNode* end);
vector<AstarNode*> findPath();
~Astar();
};
Astar.cpp源码
#include "stdafx.h"
#include "Astar.h"
#include "stdafx.h"
#include "MinHeap.h"
AstarRunData::AstarRunData(int nodeNum, AstarNode** nodes):astar(NULL),pathID(0)
{
this->nodeCount = nodeNum;
runNodes = new AstarNodeRun*[nodeCount];
openNodesHeap = new MinHeap(512);
for(int i=0;i<nodeCount;i++)
{
runNodes[i] = new AstarNodeRun();
runNodes[i]->node = nodes[i];
}
}
void AstarRunData::clearPathId()
{
for(int i=0;i<nodeCount;i++)
{
runNodes[i]->pathID = 0;
}
}
void AstarRunData::init(Astar* p)
{
astar= p;
pathID = p->pathID;
openNodesHeap->clear();
}
AstarRunData::~AstarRunData()
{
astar = NULL;
if(runNodes != NULL)
{
delete runNodes;
runNodes = NULL;
}
}
unsigned short Astar::nextPathID = 0;
Astar::Astar():runData(NULL),startNode(NULL),endNode(NULL),searchedNodes(0)
{
pathID = nextPathID++;
if(pathID == 0)
{
pathID = nextPathID++;
}
}
AstarNodeRun* Astar::getNodeRun(int nodeIndex)
{
if(nodeIndex >=0)
{
return runData->runNodes[nodeIndex];
}
return NULL;
}
void Astar::init(AstarRunData* runData, AstarNode* start, AstarNode* end)
{
this->runData = runData;
if(pathID < runData->pathID)
{
runData->clearPathId();
}
runData->init(this);
this->startNode = start;
this->endNode = end;
}
vector<AstarNode*> Astar::findPath()
{
vector<AstarNode*> path;
AstarNodeRun* startNodeRun = getNodeRun(startNode->nodeIndex);
startNodeRun->pathID = pathID;
startNodeRun->parent = NULL;
startNodeRun->g = 0;
startNodeRun->h = startNode->getH(endNode);
startNodeRun->nodeValue = startNodeRun->f();
AstarNodeRun* currentNodeRun = startNodeRun;
while(true)
{
searchedNodes++;
if(currentNodeRun->node == endNode)
{
AstarNodeRun* c = currentNodeRun;
while(c != NULL)
{
path.push_back(c->node);
c = c->parent;
}
std::reverse(path.begin(),path.end());
break;
}
int connectNum = currentNodeRun->node->connectNum;
for(int i=0; i<connectNum; i++)
{
AstarNode* nextNode = currentNodeRun->node->connects[i];
double cost = currentNodeRun->node->getCost(i);
if(cost < 0)
{
continue;
}
AstarNodeRun* nextNodeRun = getNodeRun(nextNode->nodeIndex);
if(nextNodeRun->pathID != runData->pathID)
{
nextNodeRun->parent = currentNodeRun;
nextNodeRun->pathID = runData->pathID;
nextNodeRun->h = nextNodeRun->node->getH(endNode);
nextNodeRun->g = currentNodeRun->g + cost;
nextNodeRun->nodeValue = nextNodeRun->f();
nextNodeRun->isOpen = true;
runData->openNodesHeap->add(nextNodeRun);
}
else
{
if (currentNodeRun->g + cost < nextNodeRun->g)
{
nextNodeRun->parent = currentNodeRun;
nextNodeRun->g = currentNodeRun->g + cost;
nextNodeRun->nodeValue = nextNodeRun->f();
if(nextNodeRun->isOpen)
{
runData->openNodesHeap->up(nextNodeRun->nodeIndex);
}
else
{
runData->openNodesHeap->add(nextNodeRun);
}
}
}
}
if(runData->openNodesHeap->size() ==0)
{
break;
}
currentNodeRun = (AstarNodeRun*) runData->openNodesHeap->removeMin();
currentNodeRun->isOpen = false;
}
return path;
}
Astar::~Astar()
{
startNode = NULL;
endNode = NULL;
}
NaviGraph.h源码
#include "stdafx.h"
#include "Astar.h"
#pragma once
struct Int2
{
public:
Int2(){x = 0; y = 0;}
int x;
int y;
};
class TriangleAstarNode : public AstarNode
{
public:
Int2* vectices;
TriangleAstarNode** triangleConnects;
double* costs;
Int2 center;
public:
TriangleAstarNode(Int2* vectices, int nodeIndex):AstarNode(nodeIndex)
{
this->vectices = vectices;
center.x= 0;
center.y = 0;
for(int i=0; i<3; i++)
{
Int2 targetCenter = vectices[i];
center.x += targetCenter.x;
center.y += targetCenter.y;
}
center.x /= 3;
center.y /= 3;
costs = new double[3];
}
void setConnects(TriangleAstarNode** connects, int connectNum)
{
this->triangleConnects = connects;
this->connects = (AstarNode**)(this->triangleConnects);
this->connectNum = connectNum;
for(int i=0; i<connectNum;i++)
{
if(connects[i] != NULL)
{
Int2 pos = connects[i]->center;
costs[i] = sqrt(1.0*((pos.x-center.x)*(pos.x- center.x) + (pos.y-center.y)*(pos.y- center.y)));
}
else
{
costs[i] = -1;
}
}
}
virtual double getH(AstarNode* target)
{
Int2 targetPos = ((TriangleAstarNode*)target)->center;
return sqrt(1.0*((targetPos.x-center.x)*(targetPos.x-center.x)+(targetPos.y-center.y)*(targetPos.y-center.y)));
}
virtual double getCost(int i)
{
return costs[i];
}
};
class NaviGraph
{
public:
AstarNode** astarNodes;
int nodeCount;
AstarRunData* runData;
NaviGraph():astarNodes(NULL),nodeCount(0),runData(NULL){}
void init(int nodeCount, AstarNode** astarNodes)
{
this->nodeCount = nodeCount;
this->astarNodes = astarNodes;
this->runData = new AstarRunData(nodeCount, astarNodes);
}
};
PathFinder源码
#pragma once
#include "stdafx.h"
#include "NaviGraph.h"
class PathFinder
{
public:
NaviGraph* graph;
PathFinder()
{
graph = new NaviGraph();
}
vector<AstarNode*> findPath(AstarNode* startNode, AstarNode* endNode)
{
Astar* astar= new Astar();
astar->init(graph->runData, startNode, endNode);
return astar->findPath();
}
};
AstarTest.h源码
#include "stdafx.h"
#include "Astar.h"
#include "NaviGraph.h"
#include "PathFinder.h"
#include <iostream>
using namespace std;
class AstarTest
{
public:
void doTest()
{
Int2 v[7];
v[0].x = 200;v[0].y = 0;
v[1].x = 0;v[1].y = 200;
v[2].x = 200;v[2].y = 200;
v[3].x = 100;v[3].y = 500;
v[4].x = 400;v[4].y = 400;
v[5].x = 600;v[5].y = 700;
v[6].x = 800;v[6].y = 100;
int nodeVIndexs[][3] = {{0,1,2},{1,3,2},{2,3,4},{4,3,5},{4,5,6},{0,4,6},{0,2,4}};
TriangleAstarNode** nodes = new TriangleAstarNode*[7];
for(int i=0;i<7;i++)
{
Int2 nodeV[3];
nodeV[0] = v[nodeVIndexs[i][0]];
nodeV[1] = v[nodeVIndexs[i][1]];
nodeV[2] = v[nodeVIndexs[i][2]];
nodes[i] = new TriangleAstarNode(nodeV,i);
}
int nodeCIndexs[][3] = {{-1,1,6},{-1,2,0},{1,3,6},{2,-1,4},{3,-1,5},{6,4,-1},{0,2,5}};
for(int i=0; i<7;i++)
{
TriangleAstarNode** connects = new TriangleAstarNode*[3];
connects[0] = (nodeCIndexs[i][0]>=0?nodes[nodeCIndexs[i][0]]:NULL);
connects[1] = (nodeCIndexs[i][1]>=0?nodes[nodeCIndexs[i][1]]:NULL);
connects[2] = (nodeCIndexs[i][2]>=0?nodes[nodeCIndexs[i][2]]:NULL);
nodes[i]->setConnects(connects,3);
}
PathFinder* pathFinder = new PathFinder();
pathFinder->graph->init(7,(AstarNode**)nodes);
vector<AstarNode*> nodePath = pathFinder->findPath(nodes[3], nodes[5]);
for(int i=0; i<nodePath.size(); i++)
{
cout << nodePath[i]->nodeIndex << " ";
}
cout <<endl;
}
};