18
18
} ) ( function ( ) {
19
19
20
20
var astar = {
21
- init : function ( grid ) {
22
- for ( var x = 0 , xl = grid . length ; x < xl ; x ++ ) {
23
- for ( var y = 0 , yl = grid [ x ] . length ; y < yl ; y ++ ) {
24
- var node = grid [ x ] [ y ] ;
25
- node . f = 0 ;
26
- node . g = 0 ;
27
- node . h = 0 ;
28
- node . cost = node . type ;
29
- node . visited = false ;
30
- node . closed = false ;
31
- node . parent = null ;
32
- }
21
+ init : function ( graph ) {
22
+ for ( var i = 0 , len = graph . nodes . length ; i < len ; ++ i ) {
23
+ var node = graph . nodes [ i ] ;
24
+ node . f = 0 ;
25
+ node . g = 0 ;
26
+ node . h = 0 ;
27
+ node . cost = node . type ;
28
+ node . visited = false ;
29
+ node . closed = false ;
30
+ node . parent = null ;
33
31
}
34
32
} ,
35
33
heap : function ( ) {
@@ -42,24 +40,22 @@ var astar = {
42
40
// supported options:
43
41
// {
44
42
// heuristic: heuristic function to use
45
- // diagonal: boolean specifying whether diagonal moves are allowed
46
43
// closest: boolean specifying whether to return closest node if
47
44
// target is unreachable
48
45
// }
49
- search : function ( grid , start , end , options ) {
50
- astar . init ( grid ) ;
46
+ search : function ( graph , start , end , options ) {
47
+ astar . init ( graph ) ;
51
48
52
49
options = options || { } ;
53
- var heuristic = options . heuristic || astar . manhattan ;
54
- var diagonal = ! ! options . diagonal ;
50
+ var heuristic = options . heuristic || astar . heuristics . manhattan ;
55
51
var closest = options . closest || false ;
56
52
57
53
var openHeap = astar . heap ( ) ;
58
54
59
55
// set the start node to be the closest if required
60
56
var closestNode = start ;
61
57
62
- start . h = heuristic ( start . pos , end . pos ) ;
58
+ start . h = heuristic ( start , end ) ;
63
59
64
60
function pathTo ( node ) {
65
61
var curr = node ;
@@ -87,8 +83,8 @@ var astar = {
87
83
// Normal case -- move currentNode from open to closed, process each of its neighbors.
88
84
currentNode . closed = true ;
89
85
90
- // Find all neighbors for the current node. Optionally find diagonal neighbors as well (false by default).
91
- var neighbors = astar . neighbors ( grid , currentNode , diagonal ) ;
86
+ // Find all neighbors for the current node.
87
+ var neighbors = graph . neighbors ( currentNode ) ;
92
88
93
89
for ( var i = 0 , il = neighbors . length ; i < il ; i ++ ) {
94
90
var neighbor = neighbors [ i ] ;
@@ -108,7 +104,7 @@ var astar = {
108
104
// Found an optimal (so far) path to this node. Take score for node to see how good it is.
109
105
neighbor . visited = true ;
110
106
neighbor . parent = currentNode ;
111
- neighbor . h = neighbor . h || heuristic ( neighbor . pos , end . pos ) ;
107
+ neighbor . h = neighbor . h || heuristic ( neighbor , end ) ;
112
108
neighbor . g = gScore ;
113
109
neighbor . f = neighbor . g + neighbor . h ;
114
110
@@ -141,24 +137,70 @@ var astar = {
141
137
// No result was found - empty array signifies failure to find path.
142
138
return [ ] ;
143
139
} ,
144
- manhattan : function ( pos0 , pos1 ) {
145
- // See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
140
+ // See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
141
+ heuristics : {
142
+ manhattan : function ( pos0 , pos1 ) {
143
+ var d1 = Math . abs ( pos1 . x - pos0 . x ) ;
144
+ var d2 = Math . abs ( pos1 . y - pos0 . y ) ;
145
+ return d1 + d2 ;
146
+ } ,
147
+ diagonal : function ( pos0 , pos1 ) {
148
+ var D = 1 ;
149
+ var D2 = Math . sqrt ( 2 ) ;
150
+ var d1 = Math . abs ( pos1 . x - pos0 . x ) ;
151
+ var d2 = Math . abs ( pos1 . y - pos0 . y ) ;
152
+ return ( D * ( d1 + d2 ) ) + ( ( D2 - ( 2 * D ) ) * Math . min ( d1 , d2 ) ) ;
153
+ } ,
154
+ gps : function ( node0 , node1 ) {
155
+ var x = ( node1 . longRad - node0 . longRad ) * Math . cos ( ( node0 . latRad + node1 . latRad ) / 2 ) ,
156
+ y = node1 . latRad - node0 . latRad ,
157
+ res = Math . sqrt ( Math . pow ( x , 2 ) + Math . pow ( y , 2 ) ) * 6371 ;
158
+ //printErr("Distance from " + node0.name + " to " + node1.name + " = " + res);
159
+ return res ;
160
+ }
161
+ }
162
+ } ;
146
163
147
- var d1 = Math . abs ( pos1 . x - pos0 . x ) ;
148
- var d2 = Math . abs ( pos1 . y - pos0 . y ) ;
149
- return d1 + d2 ;
150
- } ,
151
- diagonal : function ( pos0 , pos1 ) {
152
- var D = 1 ;
153
- var D2 = Math . sqrt ( 2 ) ;
154
- var d1 = Math . abs ( pos1 . x - pos0 . x ) ;
155
- var d2 = Math . abs ( pos1 . y - pos0 . y ) ;
156
- return ( D * ( d1 + d2 ) ) + ( ( D2 - ( 2 * D ) ) * Math . min ( d1 , d2 ) ) ;
157
- } ,
158
- neighbors : function ( grid , node , diagonals ) {
159
- var ret = [ ] ;
160
- var x = node . x ;
161
- var y = node . y ;
164
+ /**
165
+ * A graph memory structure
166
+ * @param {Array } [gridIn] Facultative grid of input weights
167
+ * @param {bool } [diagonal] Specify whether diagonal moves are allowed
168
+ */
169
+ function Graph ( gridIn , diagonal ) {
170
+ var nodes = [ ] ;
171
+
172
+ if ( gridIn ) {
173
+ var grid = [ ] ,
174
+ node ;
175
+ for ( var x = 0 ; x < gridIn . length ; x ++ ) {
176
+ grid [ x ] = [ ] ;
177
+
178
+ for ( var y = 0 , row = gridIn [ x ] ; y < row . length ; y ++ ) {
179
+ node = new GraphNode ( x , y , row [ y ] ) ;
180
+ grid [ x ] [ y ] = node ;
181
+ nodes . push ( node ) ;
182
+ }
183
+ }
184
+ this . grid = grid ;
185
+ }
186
+
187
+ this . nodes = nodes ;
188
+ this . diagonal = ! ! diagonal ; // Optionally find diagonal neighbors as well (false by default).
189
+ }
190
+
191
+ Graph . prototype . add = function ( node ) {
192
+ if ( this . nodes . indexOf ( node ) == - 1 ) {
193
+ this . nodes . push ( node ) ;
194
+ }
195
+ } ;
196
+
197
+ Graph . prototype . neighbors = function ( node ) {
198
+ var ret = [ ] ,
199
+ x = node . x ,
200
+ y = node . y ;
201
+
202
+ if ( this . grid ) {
203
+ var grid = this . grid ;
162
204
163
205
// West
164
206
if ( grid [ x - 1 ] && grid [ x - 1 ] [ y ] ) {
@@ -180,8 +222,7 @@ var astar = {
180
222
ret . push ( grid [ x ] [ y + 1 ] ) ;
181
223
}
182
224
183
- if ( diagonals ) {
184
-
225
+ if ( this . diagonal ) {
185
226
// Southwest
186
227
if ( grid [ x - 1 ] && grid [ x - 1 ] [ y - 1 ] ) {
187
228
ret . push ( grid [ x - 1 ] [ y - 1 ] ) ;
@@ -201,27 +242,14 @@ var astar = {
201
242
if ( grid [ x + 1 ] && grid [ x + 1 ] [ y + 1 ] ) {
202
243
ret . push ( grid [ x + 1 ] [ y + 1 ] ) ;
203
244
}
204
-
205
245
}
206
-
207
- return ret ;
208
246
}
209
- } ;
210
-
211
- function Graph ( grid ) {
212
- var nodes = [ ] ;
213
-
214
- for ( var x = 0 ; x < grid . length ; x ++ ) {
215
- nodes [ x ] = [ ] ;
216
-
217
- for ( var y = 0 , row = grid [ x ] ; y < row . length ; y ++ ) {
218
- nodes [ x ] [ y ] = new GraphNode ( x , y , row [ y ] ) ;
219
- }
247
+ else {
248
+ // Your neighbors implementation!
220
249
}
221
250
222
- this . input = grid ;
223
- this . nodes = nodes ;
224
- }
251
+ return ret ;
252
+ } ;
225
253
226
254
Graph . prototype . toString = function ( ) {
227
255
var graphString = "\n" ;
@@ -239,13 +267,8 @@ Graph.prototype.toString = function() {
239
267
} ;
240
268
241
269
function GraphNode ( x , y , type ) {
242
- this . data = { } ;
243
270
this . x = x ;
244
271
this . y = y ;
245
- this . pos = {
246
- x : x ,
247
- y : y
248
- } ;
249
272
this . type = type ;
250
273
}
251
274
0 commit comments