Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added basic GUI controls with stepping, restart, diagonals option. Node info. Refactoring. #9

Merged
merged 9 commits into from
Jan 18, 2017
131 changes: 131 additions & 0 deletions astarpathfinder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@

function AStarPathFinder(map, start, end, allowDiagonals) {
this.map = map;
this.lastCheckedNode = start;
this.openSet = [];
// openSet starts with beginning node only
this.openSet.push(start);
this.closedSet = [];
this.start = start;
this.end = end;
this.allowDiagonals = allowDiagonals;

//This function returns a measure of aesthetic preference for
//use when ordering the openSet. It is used to prioritise
//between equal standard heuristic scores. It can therefore
//be anything you like without affecting the ability to find
//a minimum cost path.

this.visualDist = function(a, b) {
return dist(a.i, a.j, b.i, b.j);
}

// An educated guess of how far it is between two points

this.heuristic = function(a, b) {
var d;
if (allowDiagonals) {
d = dist(a.i, a.j, b.i, b.j);
} else {
d = abs(a.i - b.i) + abs(a.j - b.j);
}
return d;
}

// Function to delete element from the array
this.removeFromArray = function(arr, elt) {
// Could use indexOf here instead to be more efficient
for (var i = arr.length - 1; i >= 0; i--) {
if (arr[i] == elt) {
arr.splice(i, 1);
}
}
}

//Run one finding step.
//returns 0 if search ongoing
//returns 1 if goal reached
//returns -1 if no solution
this.step = function() {

if (this.openSet.length > 0) {

// Best next option
var winner = 0;
for (var i = 1; i < this.openSet.length; i++) {
if (this.openSet[i].f < this.openSet[winner].f) {
winner = i;
}
//if we have a tie according to the standard heuristic
if (this.openSet[i].f == this.openSet[winner].f) {
//Prefer to explore options with longer known paths (closer to goal)
if (this.openSet[i].g > this.openSet[winner].g) {
winner = i;
}
//if we're using Manhattan distances then also break ties
//of the known distance measure by using the visual heuristic.
//This ensures that the search concentrates on routes that look
//more direct. This makes no difference to the actual path distance
//but improves the look for things like games or more closely
//approximates the real shortest path if using grid sampled data for
//planning natural paths.
if (!this.allowDiagonals) {
if (this.openSet[i].g == this.openSet[winner].g &&
this.openSet[i].vh < this.openSet[winner].vh) {
winner = i;
}
}
}
}
var current = this.openSet[winner];
this.lastCheckedNode = current;

// Did I finish?
if (current === this.end) {
console.log("DONE!");
return 1;
}

// Best option moves from openSet to closedSet
this.removeFromArray(this.openSet, current);
this.closedSet.push(current);

// Check all the neighbors
var neighbors = current.getNeighbors();

for (var i = 0; i < neighbors.length; i++) {
var neighbor = neighbors[i];

// Valid next spot?
if (!this.closedSet.includes(neighbor)) {
var tempG = current.g + this.heuristic(neighbor, current);

// Is this a better path than before?
var tempG = current.g + this.heuristic(neighbor, current);

// Is this a better path than before?
if (!this.openSet.includes(neighbor)) {
this.openSet.push(neighbor);
} else if (tempG >= neighbor.g) {
// No, it's not a better path
continue;
}

neighbor.g = tempG;
neighbor.h = this.heuristic(neighbor, end);
if (allowDiagonals) {
neighbor.vh = this.visualDist(neighbor, end);
}
neighbor.f = neighbor.g + neighbor.h;
neighbor.previous = current;
}

}
return 0;
// Uh oh, no solution
} else {
console.log('no solution');
return -1;
}
}
}
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
<script language="javascript" type="text/javascript" src="libraries/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<script language="javascript" type="text/javascript" src="spot.js"></script>
<script language="javascript" type="text/javascript" src="searchmap.js"></script>
<script language="javascript" type="text/javascript" src="astarpathfinder.js"></script>
<style>
body {
padding: 20px;
Expand Down
32 changes: 32 additions & 0 deletions searchmap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
function SearchMap(cols, rows, x, y, w, h, allowDiagonals, wallRatio ) {
// How many columns and rows?
this.cols = cols;
this.rows = rows;

// This will the 2D array
this.grid = [];
this.path = [];

this.x = x;
this.y = y;
this.w = w;
this.h = h;

// Making a 2D array
for (var i = 0; i < cols; i++) {
this.grid[i] = [];
}

for (var i = 0; i < cols; i++) {
for (var j = 0; j < rows; j++) {
var isWall = random(1.0) < wallRatio;
this.grid[i][j] = new Spot(i, j, x + i * w / cols, y + j * h / rows, w / cols, h / rows, isWall, this.grid);
}
}

//for (var i = 0; i < cols; i++) {
// for (var j = 0; j < rows; j++) {
// this.grid[i][j].addNeighbors(this.grid, allowDiagonals);
// }
//}
}
Loading