mirror of
https://github.com/bensuperpc/astar.git
synced 2026-05-05 10:55:18 +02:00
new1
This commit is contained in:
+23
-33
@@ -74,36 +74,36 @@ class Node {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace Heuristic {
|
namespace Heuristic {
|
||||||
static inline Vec2i deltaVec(const Vec2i& source, const Vec2i& target) noexcept {
|
static inline Vec2i deltaVec(const Vec2i& start, const Vec2i& target) noexcept {
|
||||||
return {std::abs(source.x - target.x), std::abs(source.y - target.y)};
|
return {std::abs(start.x - target.x), std::abs(start.y - target.y)};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t manhattan(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept {
|
static inline uint32_t manhattan(const Vec2i& start, const Vec2i& target, const uint32_t weight) noexcept {
|
||||||
auto delta = deltaVec(source, target);
|
auto delta = deltaVec(start, target);
|
||||||
return weight * (delta.x + delta.y);
|
return weight * (delta.x + delta.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t octagonal(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept {
|
static inline uint32_t octagonal(const Vec2i& start, const Vec2i& target, const uint32_t weight) noexcept {
|
||||||
auto delta = deltaVec(source, target);
|
auto delta = deltaVec(start, target);
|
||||||
return weight * (delta.x + delta.y) + (-6) * std::min(delta.x, delta.y);
|
return weight * (delta.x + delta.y) + (-6) * std::min(delta.x, delta.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t euclidean(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept {
|
static inline uint32_t euclidean(const Vec2i& start, const Vec2i& target, const uint32_t weight) noexcept {
|
||||||
auto delta = deltaVec(source, target);
|
auto delta = deltaVec(start, target);
|
||||||
return weight * static_cast<uint32_t>(std::sqrt(std::pow(delta.x, 2) + std::pow(delta.y, 2)));
|
return weight * static_cast<uint32_t>(std::sqrt(std::pow(delta.x, 2) + std::pow(delta.y, 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t chebyshev(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept {
|
static inline uint32_t chebyshev(const Vec2i& start, const Vec2i& target, const uint32_t weight) noexcept {
|
||||||
auto delta = deltaVec(source, target);
|
auto delta = deltaVec(start, target);
|
||||||
return weight * std::max(delta.x, delta.y);
|
return weight * std::max(delta.x, delta.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t euclideanNoSQR(const Vec2i& source, const Vec2i& target, const uint32_t weight) noexcept {
|
static inline uint32_t euclideanNoSQR(const Vec2i& start, const Vec2i& target, const uint32_t weight) noexcept {
|
||||||
auto delta = deltaVec(source, target);
|
auto delta = deltaVec(start, target);
|
||||||
return weight * static_cast<uint32_t>(std::pow(delta.x, 2) + std::pow(delta.y, 2));
|
return weight * static_cast<uint32_t>(std::pow(delta.x, 2) + std::pow(delta.y, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr uint32_t dijkstra([[maybe_unused]] const Vec2i& source,
|
static constexpr uint32_t dijkstra([[maybe_unused]] const Vec2i& start,
|
||||||
[[maybe_unused]] const Vec2i& target,
|
[[maybe_unused]] const Vec2i& target,
|
||||||
const uint32_t weight = 0) noexcept {
|
const uint32_t weight = 0) noexcept {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -159,13 +159,13 @@ class AStarVirtual {
|
|||||||
std::function<void(Node<CoordinateType>*)> _debugOpenNode;
|
std::function<void(Node<CoordinateType>*)> _debugOpenNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using IsWalkableFn = std::function<bool(Vec2i)>;
|
||||||
template <IntegerType CoordinateType = uint32_t, bool enableDebug = false>
|
template <IntegerType CoordinateType = uint32_t, bool enableDebug = false>
|
||||||
class AStar final : public AStarVirtual<CoordinateType, enableDebug> {
|
class AStar final : public AStarVirtual<CoordinateType, enableDebug> {
|
||||||
public:
|
public:
|
||||||
explicit AStar() {}
|
explicit AStar() {}
|
||||||
|
std::vector<Vec2i> findPath(const Vec2i start, const Vec2i target, const Vec2i worldSize, IsWalkableFn isWalkable) {
|
||||||
std::vector<Vec2i> findPath(const Vec2i source, const Vec2i& target) {
|
if (target.x < 0 || target.x >= worldSize.x || target.y < 0 || target.y >= worldSize.y) {
|
||||||
if (target.x < 0 || target.x >= _worldSize.x || target.y < 0 || target.y >= _worldSize.y) {
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,8 +178,8 @@ class AStar final : public AStarVirtual<CoordinateType, enableDebug> {
|
|||||||
std::unordered_map<Vec2i, Node<CoordinateType>*, Vec2i::hash> openNodeMap;
|
std::unordered_map<Vec2i, Node<CoordinateType>*, Vec2i::hash> openNodeMap;
|
||||||
std::unordered_map<Vec2i, Node<CoordinateType>*, Vec2i::hash> closedNodeMap;
|
std::unordered_map<Vec2i, Node<CoordinateType>*, Vec2i::hash> closedNodeMap;
|
||||||
|
|
||||||
openNodeVecPQueue.push(new Node<CoordinateType>(source));
|
openNodeVecPQueue.push(new Node<CoordinateType>(start));
|
||||||
openNodeMap.insert({source, openNodeVecPQueue.top()});
|
openNodeMap.insert({start, openNodeVecPQueue.top()});
|
||||||
|
|
||||||
while (!openNodeVecPQueue.empty()) {
|
while (!openNodeVecPQueue.empty()) {
|
||||||
currentNode = openNodeVecPQueue.top();
|
currentNode = openNodeVecPQueue.top();
|
||||||
@@ -199,7 +199,7 @@ class AStar final : public AStarVirtual<CoordinateType, enableDebug> {
|
|||||||
for (size_t i = 0; i < AStarVirtual<CoordinateType, enableDebug>::_directionsCount; ++i) {
|
for (size_t i = 0; i < AStarVirtual<CoordinateType, enableDebug>::_directionsCount; ++i) {
|
||||||
Vec2i newPos = currentNode->pos + AStarVirtual<CoordinateType, enableDebug>::_directions[i];
|
Vec2i newPos = currentNode->pos + AStarVirtual<CoordinateType, enableDebug>::_directions[i];
|
||||||
|
|
||||||
if (_obstacles.contains(newPos)) {
|
if (!isWalkable(newPos)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ class AStar final : public AStarVirtual<CoordinateType, enableDebug> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPos.x < 0 || newPos.x >= _worldSize.x || newPos.y < 0 || newPos.y >= _worldSize.y) {
|
if (newPos.x < 0 || newPos.x >= worldSize.x || newPos.y < 0 || newPos.y >= worldSize.y) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,17 +251,7 @@ class AStar final : public AStarVirtual<CoordinateType, enableDebug> {
|
|||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addObstacle(const Vec2i& pos) { _obstacles.insert(pos); }
|
|
||||||
void removeObstacle(const Vec2i& pos) { _obstacles.erase(pos); }
|
|
||||||
std::unordered_set<Vec2i, Vec2i::hash>& getObstacles() noexcept { return _obstacles; }
|
|
||||||
|
|
||||||
void clear() { _obstacles.clear(); }
|
|
||||||
void setWorldSize(const Vec2i& worldSize_) noexcept { _worldSize = worldSize_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_set<Vec2i, Vec2i::hash> _obstacles;
|
|
||||||
Vec2i _worldSize = {0, 0};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fast AStar are faster than normal AStar but use more ram and direct access to the map
|
// Fast AStar are faster than normal AStar but use more ram and direct access to the map
|
||||||
@@ -271,7 +261,7 @@ class AStarFast final : public AStarVirtual<CoordinateType, enableDebug> {
|
|||||||
explicit AStarFast() : _isObstacleFunction([](MapElementType value) { return value == 1; }) {}
|
explicit AStarFast() : _isObstacleFunction([](MapElementType value) { return value == 1; }) {}
|
||||||
|
|
||||||
// Same as AStar::findPath() but use direct access to the map
|
// Same as AStar::findPath() but use direct access to the map
|
||||||
std::vector<Vec2i> findPath(const Vec2i& source, const Vec2i& target, const std::vector<MapElementType>& map, const Vec2i& worldSize) {
|
std::vector<Vec2i> findPath(const Vec2i& start, const Vec2i& target, const std::vector<MapElementType>& map, const Vec2i& worldSize) {
|
||||||
if (target.x < 0 || target.x >= worldSize.x || target.y < 0 || target.y >= worldSize.y) {
|
if (target.x < 0 || target.x >= worldSize.x || target.y < 0 || target.y >= worldSize.y) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -284,8 +274,8 @@ class AStarFast final : public AStarVirtual<CoordinateType, enableDebug> {
|
|||||||
std::unordered_map<Vec2i, Node<CoordinateType>*, Vec2i::hash> openNodeMap;
|
std::unordered_map<Vec2i, Node<CoordinateType>*, Vec2i::hash> openNodeMap;
|
||||||
std::unordered_map<Vec2i, Node<CoordinateType>*, Vec2i::hash> closedNodeMap;
|
std::unordered_map<Vec2i, Node<CoordinateType>*, Vec2i::hash> closedNodeMap;
|
||||||
|
|
||||||
openNodeVecPQueue.push(new Node<CoordinateType>(source));
|
openNodeVecPQueue.push(new Node<CoordinateType>(start));
|
||||||
openNodeMap.insert({source, openNodeVecPQueue.top()});
|
openNodeMap.insert({start, openNodeVecPQueue.top()});
|
||||||
|
|
||||||
while (!openNodeVecPQueue.empty()) {
|
while (!openNodeVecPQueue.empty()) {
|
||||||
currentNode = openNodeVecPQueue.top();
|
currentNode = openNodeVecPQueue.top();
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ static void astar_bench(benchmark::State& state) {
|
|||||||
|
|
||||||
AStar::AStar<CoordinateType, false> pathFinder;
|
AStar::AStar<CoordinateType, false> pathFinder;
|
||||||
benchmark::DoNotOptimize(pathFinder);
|
benchmark::DoNotOptimize(pathFinder);
|
||||||
pathFinder.setWorldSize({mapWidth, mapHeight});
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
||||||
pathFinder.setDiagonalMovement(true);
|
pathFinder.setDiagonalMovement(true);
|
||||||
|
|
||||||
@@ -62,15 +61,12 @@ static void astar_bench(benchmark::State& state) {
|
|||||||
blocks[index] = 0;
|
blocks[index] = 0;
|
||||||
} else {
|
} else {
|
||||||
blocks[index] = 1;
|
blocks[index] = 1;
|
||||||
pathFinder.addObstacle({static_cast<int32_t>(x), static_cast<int32_t>(y)});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks[0] = 0;
|
blocks[0] = 0;
|
||||||
pathFinder.removeObstacle({0, 0});
|
|
||||||
blocks[mapWidth * mapHeight - 1] = 0;
|
blocks[mapWidth * mapHeight - 1] = 0;
|
||||||
pathFinder.removeObstacle({mapWidth - 1, mapHeight - 1});
|
|
||||||
|
|
||||||
AStar::Vec2i source(0, 0);
|
AStar::Vec2i source(0, 0);
|
||||||
AStar::Vec2i target(mapWidth - 1, mapHeight - 1);
|
AStar::Vec2i target(mapWidth - 1, mapHeight - 1);
|
||||||
@@ -78,8 +74,15 @@ static void astar_bench(benchmark::State& state) {
|
|||||||
std::vector<AStar::Vec2i> path;
|
std::vector<AStar::Vec2i> path;
|
||||||
benchmark::DoNotOptimize(path);
|
benchmark::DoNotOptimize(path);
|
||||||
|
|
||||||
|
std::function<bool(AStar::Vec2i)> isWalkable = [&blocks, mapWidth, mapHeight](AStar::Vec2i pos) {
|
||||||
|
if (pos.x < 0 || pos.x >= mapWidth || pos.y < 0 || pos.y >= mapHeight) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return blocks[pos.x + pos.y * mapWidth] == 0;
|
||||||
|
};
|
||||||
|
|
||||||
for (auto _ : state) {
|
for (auto _ : state) {
|
||||||
path = pathFinder.findPath(source, target);
|
path = pathFinder.findPath(source, target, {mapWidth, mapHeight}, isWalkable);
|
||||||
state.PauseTiming();
|
state.PauseTiming();
|
||||||
if (path.size() == 0) {
|
if (path.size() == 0) {
|
||||||
state.SkipWithError("No path found");
|
state.SkipWithError("No path found");
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ auto main() -> int {
|
|||||||
generator_2.setMultiplier((uint32_t)multiplier);
|
generator_2.setMultiplier((uint32_t)multiplier);
|
||||||
|
|
||||||
AStar::AStar<uint32_t, false> pathFinder;
|
AStar::AStar<uint32_t, false> pathFinder;
|
||||||
pathFinder.setWorldSize({mapWidth, mapHeight});
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::manhattan);
|
pathFinder.setHeuristic(AStar::Heuristic::manhattan);
|
||||||
pathFinder.setDiagonalMovement(true);
|
pathFinder.setDiagonalMovement(true);
|
||||||
|
|
||||||
@@ -95,8 +94,6 @@ auto main() -> int {
|
|||||||
generator_2.setWeightedStrength(weighted_strength);
|
generator_2.setWeightedStrength(weighted_strength);
|
||||||
generator_2.setMultiplier((uint32_t)multiplier);
|
generator_2.setMultiplier((uint32_t)multiplier);
|
||||||
|
|
||||||
pathFinder.clear();
|
|
||||||
|
|
||||||
heightmap = generator_2.generate2dMeightmap(0, 0, 0, screenWidth, 0, screenHeight);
|
heightmap = generator_2.generate2dMeightmap(0, 0, 0, screenWidth, 0, screenHeight);
|
||||||
|
|
||||||
for (uint64_t x = 0; x < mapWidth; x++) {
|
for (uint64_t x = 0; x < mapWidth; x++) {
|
||||||
@@ -108,18 +105,22 @@ auto main() -> int {
|
|||||||
blocks[index] = 0;
|
blocks[index] = 0;
|
||||||
} else {
|
} else {
|
||||||
blocks[index] = 1;
|
blocks[index] = 1;
|
||||||
pathFinder.addObstacle({static_cast<int32_t>(x), static_cast<int32_t>(y)});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blocks[0] = 0;
|
blocks[0] = 0;
|
||||||
pathFinder.removeObstacle({0, 0});
|
|
||||||
blocks[mapWidth * mapHeight - 1] = 0;
|
blocks[mapWidth * mapHeight - 1] = 0;
|
||||||
pathFinder.removeObstacle({mapWidth - 1, mapHeight - 1});
|
|
||||||
|
std::function<bool(AStar::Vec2i)> isWalkable = [&blocks, mapWidth, mapHeight](AStar::Vec2i pos) {
|
||||||
|
if (pos.x < 0 || pos.x >= mapWidth || pos.y < 0 || pos.y >= mapHeight) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return blocks[pos.x + pos.y * mapWidth] == 0;
|
||||||
|
};
|
||||||
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::manhattan);
|
pathFinder.setHeuristic(AStar::Heuristic::manhattan);
|
||||||
auto start1 = std::chrono::high_resolution_clock::now();
|
auto start1 = std::chrono::high_resolution_clock::now();
|
||||||
auto path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1});
|
auto path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}, {mapWidth, mapHeight}, isWalkable);
|
||||||
auto stop1 = std::chrono::high_resolution_clock::now();
|
auto stop1 = std::chrono::high_resolution_clock::now();
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
std::cout << "Path not found" << std::endl;
|
std::cout << "Path not found" << std::endl;
|
||||||
@@ -134,7 +135,7 @@ auto main() -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
||||||
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1});
|
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}, {mapWidth, mapHeight}, isWalkable);
|
||||||
euclideanPathSize = path.size();
|
euclideanPathSize = path.size();
|
||||||
|
|
||||||
for (auto& i : path) {
|
for (auto& i : path) {
|
||||||
@@ -143,7 +144,7 @@ auto main() -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::octagonal);
|
pathFinder.setHeuristic(AStar::Heuristic::octagonal);
|
||||||
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1});
|
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}, {mapWidth, mapHeight}, isWalkable);
|
||||||
octagonalPathSize = path.size();
|
octagonalPathSize = path.size();
|
||||||
|
|
||||||
for (auto& i : path) {
|
for (auto& i : path) {
|
||||||
@@ -152,7 +153,7 @@ auto main() -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::chebyshev);
|
pathFinder.setHeuristic(AStar::Heuristic::chebyshev);
|
||||||
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1});
|
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}, {mapWidth, mapHeight}, isWalkable);
|
||||||
chebyshevPathSize = path.size();
|
chebyshevPathSize = path.size();
|
||||||
|
|
||||||
for (auto& i : path) {
|
for (auto& i : path) {
|
||||||
@@ -161,7 +162,7 @@ auto main() -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::euclideanNoSQR);
|
pathFinder.setHeuristic(AStar::Heuristic::euclideanNoSQR);
|
||||||
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1});
|
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}, {mapWidth, mapHeight}, isWalkable);
|
||||||
euclideanNoSQRPathSize = path.size();
|
euclideanNoSQRPathSize = path.size();
|
||||||
|
|
||||||
for (auto& i : path) {
|
for (auto& i : path) {
|
||||||
@@ -170,7 +171,7 @@ auto main() -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::dijkstra);
|
pathFinder.setHeuristic(AStar::Heuristic::dijkstra);
|
||||||
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1});
|
path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}, {mapWidth, mapHeight}, isWalkable);
|
||||||
dijkstraPathSize = path.size();
|
dijkstraPathSize = path.size();
|
||||||
|
|
||||||
for (auto& i : path) {
|
for (auto& i : path) {
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ auto main() -> int {
|
|||||||
generator_2.setMultiplier((uint32_t)multiplier);
|
generator_2.setMultiplier((uint32_t)multiplier);
|
||||||
|
|
||||||
AStar::AStar<uint32_t, true> pathFinder;
|
AStar::AStar<uint32_t, true> pathFinder;
|
||||||
pathFinder.setWorldSize({mapWidth, mapHeight});
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::manhattan);
|
pathFinder.setHeuristic(AStar::Heuristic::manhattan);
|
||||||
pathFinder.setDiagonalMovement(true);
|
pathFinder.setDiagonalMovement(true);
|
||||||
|
|
||||||
@@ -90,8 +89,6 @@ auto main() -> int {
|
|||||||
generator_2.setWeightedStrength(weighted_strength);
|
generator_2.setWeightedStrength(weighted_strength);
|
||||||
generator_2.setMultiplier((uint32_t)multiplier);
|
generator_2.setMultiplier((uint32_t)multiplier);
|
||||||
|
|
||||||
pathFinder.clear();
|
|
||||||
|
|
||||||
heightmap = generator_2.generate2dMeightmap(0, 0, 0, screenWidth, 0, screenHeight);
|
heightmap = generator_2.generate2dMeightmap(0, 0, 0, screenWidth, 0, screenHeight);
|
||||||
|
|
||||||
for (uint64_t x = 0; x < mapWidth; x++) {
|
for (uint64_t x = 0; x < mapWidth; x++) {
|
||||||
@@ -103,14 +100,11 @@ auto main() -> int {
|
|||||||
blocks[index] = 0;
|
blocks[index] = 0;
|
||||||
} else {
|
} else {
|
||||||
blocks[index] = 1;
|
blocks[index] = 1;
|
||||||
pathFinder.addObstacle({static_cast<int32_t>(x), static_cast<int32_t>(y)});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blocks[0] = 0;
|
blocks[0] = 0;
|
||||||
pathFinder.removeObstacle({0, 0});
|
|
||||||
blocks[mapWidth * mapHeight - 1] = 0;
|
blocks[mapWidth * mapHeight - 1] = 0;
|
||||||
pathFinder.removeObstacle({mapWidth - 1, mapHeight - 1});
|
|
||||||
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
||||||
|
|
||||||
@@ -128,8 +122,15 @@ auto main() -> int {
|
|||||||
|
|
||||||
pathFinder.setDebugOpenNode(debugOpenNode);
|
pathFinder.setDebugOpenNode(debugOpenNode);
|
||||||
|
|
||||||
|
std::function<bool(AStar::Vec2i)> isWalkable = [&blocks, mapWidth, mapHeight](AStar::Vec2i pos) {
|
||||||
|
if (pos.x < 0 || pos.x >= mapWidth || pos.y < 0 || pos.y >= mapHeight) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return blocks[pos.x + pos.y * mapWidth] == 0;
|
||||||
|
};
|
||||||
|
|
||||||
auto start1 = std::chrono::high_resolution_clock::now();
|
auto start1 = std::chrono::high_resolution_clock::now();
|
||||||
auto path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1});
|
auto path = pathFinder.findPath({0, 0}, {mapWidth - 1, mapHeight - 1}, {mapWidth, mapHeight}, isWalkable);
|
||||||
auto stop1 = std::chrono::high_resolution_clock::now();
|
auto stop1 = std::chrono::high_resolution_clock::now();
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
std::cout << "Path not found" << std::endl;
|
std::cout << "Path not found" << std::endl;
|
||||||
|
|||||||
@@ -6,15 +6,23 @@ TEST(AStar, basic_path_1) {
|
|||||||
int mapWidth = 4;
|
int mapWidth = 4;
|
||||||
int mapHeight = 4;
|
int mapHeight = 4;
|
||||||
AStar::AStar pathFinder;
|
AStar::AStar pathFinder;
|
||||||
pathFinder.setWorldSize({mapWidth, mapWidth});
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
||||||
pathFinder.setDiagonalMovement(true);
|
pathFinder.setDiagonalMovement(true);
|
||||||
|
|
||||||
AStar::Vec2i source(0, 0);
|
AStar::Vec2i source(0, 0);
|
||||||
AStar::Vec2i target(mapWidth - 1, mapHeight - 1);
|
AStar::Vec2i target(mapWidth - 1, mapHeight - 1);
|
||||||
|
|
||||||
|
std::function<bool(AStar::Vec2i)> isWalkable = [&pathFinder](AStar::Vec2i pos) {
|
||||||
|
if (pos.x < 0 || pos.x >= 4 || pos.y < 0 || pos.y >= 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
std::cout << "AStar::AStar pathFinder;" << std::endl;
|
std::cout << "AStar::AStar pathFinder;" << std::endl;
|
||||||
auto path = pathFinder.findPath(source, target);
|
auto path = pathFinder.findPath(source, target, {mapWidth, mapHeight}, isWalkable);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXPECT_EQ(path.size(), 4);
|
EXPECT_EQ(path.size(), 4);
|
||||||
|
|
||||||
@@ -28,14 +36,20 @@ TEST(AStar, basic_path_2) {
|
|||||||
int mapWidth = 10;
|
int mapWidth = 10;
|
||||||
int mapHeight = 10;
|
int mapHeight = 10;
|
||||||
AStar::AStar pathFinder;
|
AStar::AStar pathFinder;
|
||||||
pathFinder.setWorldSize({mapWidth, mapWidth});
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
||||||
pathFinder.setDiagonalMovement(true);
|
pathFinder.setDiagonalMovement(true);
|
||||||
|
|
||||||
AStar::Vec2i source(0, 0);
|
AStar::Vec2i source(0, 0);
|
||||||
AStar::Vec2i target(mapWidth - 1, mapHeight - 1);
|
AStar::Vec2i target(mapWidth - 1, mapHeight - 1);
|
||||||
|
|
||||||
auto path = pathFinder.findPath(source, target);
|
std::function<bool(AStar::Vec2i)> isWalkable = [&pathFinder](AStar::Vec2i pos) {
|
||||||
|
if (pos.x < 0 || pos.x >= 10 || pos.y < 0 || pos.y >= 10) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto path = pathFinder.findPath(source, target, {mapWidth, mapHeight}, isWalkable);
|
||||||
|
|
||||||
EXPECT_EQ(path.size(), 10);
|
EXPECT_EQ(path.size(), 10);
|
||||||
|
|
||||||
@@ -49,14 +63,20 @@ TEST(AStar, basic_diagonal_path_wrong_1) {
|
|||||||
int mapWidth = 10;
|
int mapWidth = 10;
|
||||||
int mapHeight = 10;
|
int mapHeight = 10;
|
||||||
AStar::AStar pathFinder;
|
AStar::AStar pathFinder;
|
||||||
pathFinder.setWorldSize({mapWidth, mapHeight});
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
||||||
pathFinder.setDiagonalMovement(true);
|
pathFinder.setDiagonalMovement(true);
|
||||||
|
|
||||||
AStar::Vec2i source(0, 0);
|
AStar::Vec2i source(0, 0);
|
||||||
AStar::Vec2i target(19, 19);
|
AStar::Vec2i target(19, 19);
|
||||||
|
|
||||||
auto path = pathFinder.findPath(source, target);
|
std::function<bool(AStar::Vec2i)> isWalkable = [&pathFinder](AStar::Vec2i pos) {
|
||||||
|
if (pos.x < 0 || pos.x >= 10 || pos.y < 0 || pos.y >= 10) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto path = pathFinder.findPath(source, target, {10, 10}, isWalkable);
|
||||||
|
|
||||||
EXPECT_EQ(path.size(), 0);
|
EXPECT_EQ(path.size(), 0);
|
||||||
}
|
}
|
||||||
@@ -65,18 +85,23 @@ TEST(AStar, basic_diagonal_path_wrong_2) {
|
|||||||
int mapWidth = 10;
|
int mapWidth = 10;
|
||||||
int mapHeight = 10;
|
int mapHeight = 10;
|
||||||
AStar::AStar pathFinder;
|
AStar::AStar pathFinder;
|
||||||
pathFinder.setWorldSize({mapWidth, mapHeight});
|
|
||||||
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
pathFinder.setHeuristic(AStar::Heuristic::euclidean);
|
||||||
pathFinder.setDiagonalMovement(true);
|
pathFinder.setDiagonalMovement(true);
|
||||||
|
|
||||||
pathFinder.addObstacle({0, 1});
|
std::function<bool(AStar::Vec2i)> isWalkable = [&pathFinder](AStar::Vec2i pos) {
|
||||||
pathFinder.addObstacle({1, 1});
|
if (pos.x < 0 || pos.x >= 10 || pos.y < 0 || pos.y >= 10) {
|
||||||
pathFinder.addObstacle({1, 0});
|
return false;
|
||||||
|
}
|
||||||
|
if ((pos.x == 0 && pos.y == 1) || (pos.x == 1 && pos.y == 1) || (pos.x == 1 && pos.y == 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
AStar::Vec2i source(0, 0);
|
AStar::Vec2i source(0, 0);
|
||||||
AStar::Vec2i target(9, 9);
|
AStar::Vec2i target(9, 9);
|
||||||
|
|
||||||
auto path = pathFinder.findPath(source, target);
|
auto path = pathFinder.findPath(source, target, {10, 10}, isWalkable);
|
||||||
|
|
||||||
EXPECT_EQ(path.size(), 0);
|
EXPECT_EQ(path.size(), 0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user