diff --git a/a-star/a-greedy-star.js b/a-star/a-greedy-star.js index a4f200f..136401d 100644 --- a/a-star/a-greedy-star.js +++ b/a-star/a-greedy-star.js @@ -32,7 +32,7 @@ module.exports.l1 = heuristics.l1; * while allowing the graph to be reused without rebuilding. * @param {Function(a, b)} options.heuristic - a function that returns estimated distance between * nodes `a` and `b`. Defaults function returns 0, which makes this search equivalent to Dijkstra search. - * @param {Function(a, b)} options.distance - a function that returns actual distance between two + * @param {Function(a, b, link, parent)} options.distance - a function that returns actual distance between two * nodes `a` and `b`. By default this is set to return graph-theoretical distance (always 1); * @param {Boolean} options.oriented - whether graph should be considered oriented or not. * @@ -164,7 +164,7 @@ function aStarBi(graph, options) { function reconstructBiDirectionalPath(a, b) { var pathOfNodes = []; var aParent = a; - while(aParent) { + while (aParent) { pathOfNodes.push(aParent.node); aParent = aParent.parent; } @@ -208,7 +208,7 @@ function aStarBi(graph, options) { return; } - var tentativeDistance = cameFrom.distanceToSource + distance(otherSearchState.node, cameFrom.node, link); + var tentativeDistance = cameFrom.distanceToSource + distance(otherSearchState.node, cameFrom.node, link, cameFrom.parent && cameFrom.parent.node); if (tentativeDistance >= otherSearchState.distanceToSource) { // This would only make our path longer. Ignore this route. diff --git a/a-star/a-star.js b/a-star/a-star.js index bbcd79e..dfde5a0 100644 --- a/a-star/a-star.js +++ b/a-star/a-star.js @@ -30,7 +30,7 @@ module.exports.l1 = heuristics.l1; * nodes `a` and `b`. This function should never overestimate actual distance between two * nodes (otherwise the found path will not be the shortest). Defaults function returns 0, * which makes this search equivalent to Dijkstra search. - * @param {Function(a, b)} options.distance - a function that returns actual distance between two + * @param {Function(a, b, c)} options.distance - a function that returns actual distance between two * nodes `a` and `b`. By default this is set to return graph-theoretical distance (always 1); * @param {Boolean} options.oriented - whether graph should be considered oriented or not. * @@ -123,7 +123,7 @@ function aStarPathSearch(graph, options) { return; } - var tentativeDistance = cameFrom.distanceToSource + distance(otherNode, cameFrom.node, link); + var tentativeDistance = cameFrom.distanceToSource + distance(otherNode, cameFrom.node, link, cameFrom.parent && cameFrom.parent.node); if (tentativeDistance >= otherSearchState.distanceToSource) { // This would only make our path longer. Ignore this route. return; diff --git a/a-star/nba/index.js b/a-star/nba/index.js index f78cd60..8921ef7 100644 --- a/a-star/nba/index.js +++ b/a-star/nba/index.js @@ -29,7 +29,7 @@ module.exports.l1 = heuristics.l1; * nodes `a` and `b`. This function should never overestimate actual distance between two * nodes (otherwise the found path will not be the shortest). Defaults function returns 0, * which makes this search equivalent to Dijkstra search. - * @param {Function(a, b)} options.distance - a function that returns actual distance between two + * @param {Function(a, b, link, parent)} options.distance - a function that returns actual distance between two * nodes `a` and `b`. By default this is set to return graph-theoretical distance (always 1); * * @returns {Object} A pathfinder with single method `find()`. @@ -186,7 +186,7 @@ function nba(graph, options) { if (blocked(cameFrom.node, otherNode, link)) return; - var tentativeDistance = cameFrom.g1 + distance(cameFrom.node, otherNode, link); + var tentativeDistance = cameFrom.g1 + distance(cameFrom.node, otherNode, link, cameFrom.p1 && cameFrom.p1.node); if (tentativeDistance < otherSearchState.g1) { otherSearchState.g1 = tentativeDistance; @@ -216,7 +216,7 @@ function nba(graph, options) { if (blocked(cameFrom.node, otherNode, link)) return; - var tentativeDistance = cameFrom.g2 + distance(cameFrom.node, otherNode, link); + var tentativeDistance = cameFrom.g2 + distance(cameFrom.node, otherNode, link, cameFrom.p2 && cameFrom.p2.node); if (tentativeDistance < otherSearchState.g2) { otherSearchState.g2 = tentativeDistance; diff --git a/dist/ngraph.path.js b/dist/ngraph.path.js index f6137e9..2d20710 100644 --- a/dist/ngraph.path.js +++ b/dist/ngraph.path.js @@ -157,7 +157,7 @@ module.exports.l1 = heuristics.l1; * while allowing the graph to be reused without rebuilding. * @param {Function(a, b)} options.heuristic - a function that returns estimated distance between * nodes `a` and `b`. Defaults function returns 0, which makes this search equivalent to Dijkstra search. - * @param {Function(a, b)} options.distance - a function that returns actual distance between two + * @param {Function(a, b, link, parent)} options.distance - a function that returns actual distance between two * nodes `a` and `b`. By default this is set to return graph-theoretical distance (always 1); * @param {Boolean} options.oriented - whether graph should be considered oriented or not. * @@ -289,7 +289,7 @@ function aStarBi(graph, options) { function reconstructBiDirectionalPath(a, b) { var pathOfNodes = []; var aParent = a; - while(aParent) { + while (aParent) { pathOfNodes.push(aParent.node); aParent = aParent.parent; } @@ -333,7 +333,7 @@ function aStarBi(graph, options) { return; } - var tentativeDistance = cameFrom.distanceToSource + distance(otherSearchState.node, cameFrom.node, link); + var tentativeDistance = cameFrom.distanceToSource + distance(otherSearchState.node, cameFrom.node, link, cameFrom.parent && cameFrom.parent.node); if (tentativeDistance >= otherSearchState.distanceToSource) { // This would only make our path longer. Ignore this route. @@ -397,7 +397,7 @@ module.exports.l1 = heuristics.l1; * nodes `a` and `b`. This function should never overestimate actual distance between two * nodes (otherwise the found path will not be the shortest). Defaults function returns 0, * which makes this search equivalent to Dijkstra search. - * @param {Function(a, b)} options.distance - a function that returns actual distance between two + * @param {Function(a, b, c)} options.distance - a function that returns actual distance between two * nodes `a` and `b`. By default this is set to return graph-theoretical distance (always 1); * @param {Boolean} options.oriented - whether graph should be considered oriented or not. * @@ -490,7 +490,7 @@ function aStarPathSearch(graph, options) { return; } - var tentativeDistance = cameFrom.distanceToSource + distance(otherNode, cameFrom.node, link); + var tentativeDistance = cameFrom.distanceToSource + distance(otherNode, cameFrom.node, link, cameFrom.parent && cameFrom.parent.node); if (tentativeDistance >= otherSearchState.distanceToSource) { // This would only make our path longer. Ignore this route. return; @@ -711,7 +711,7 @@ module.exports.l1 = heuristics.l1; * nodes `a` and `b`. This function should never overestimate actual distance between two * nodes (otherwise the found path will not be the shortest). Defaults function returns 0, * which makes this search equivalent to Dijkstra search. - * @param {Function(a, b)} options.distance - a function that returns actual distance between two + * @param {Function(a, b, link, parent)} options.distance - a function that returns actual distance between two * nodes `a` and `b`. By default this is set to return graph-theoretical distance (always 1); * * @returns {Object} A pathfinder with single method `find()`. @@ -868,7 +868,7 @@ function nba(graph, options) { if (blocked(cameFrom.node, otherNode, link)) return; - var tentativeDistance = cameFrom.g1 + distance(cameFrom.node, otherNode, link); + var tentativeDistance = cameFrom.g1 + distance(cameFrom.node, otherNode, link, cameFrom.p1 && cameFrom.p1.node); if (tentativeDistance < otherSearchState.g1) { otherSearchState.g1 = tentativeDistance; @@ -898,7 +898,7 @@ function nba(graph, options) { if (blocked(cameFrom.node, otherNode, link)) return; - var tentativeDistance = cameFrom.g2 + distance(cameFrom.node, otherNode, link); + var tentativeDistance = cameFrom.g2 + distance(cameFrom.node, otherNode, link, cameFrom.p2 && cameFrom.p2.node); if (tentativeDistance < otherSearchState.g2) { otherSearchState.g2 = tentativeDistance; diff --git a/dist/ngraph.path.min.js b/dist/ngraph.path.min.js index 953dc43..0cad232 100644 --- a/dist/ngraph.path.min.js +++ b/dist/ngraph.path.min.js @@ -1 +1 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ngraphPath=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i0){for(var i=this.length>>1;i>=0;i--)this._down(i)}if(options.setNodeId){for(var i=0;i0){this.data[0]=this.data[this.length];this.setNodeId(this.data[0],0);this._down(0)}this.data.pop();return top},peek:function(){return this.data[0]},updateItem:function(pos){this._down(pos);this._up(pos)},_up:function(pos){var data=this.data;var compare=this.compare;var setNodeId=this.setNodeId;var item=data[pos];while(pos>0){var parent=pos-1>>1;var current=data[parent];if(compare(item,current)>=0)break;data[pos]=current;setNodeId(current,pos);pos=parent}data[pos]=item;setNodeId(item,pos)},_down:function(pos){var data=this.data;var compare=this.compare;var halfLength=this.length>>1;var item=data[pos];var setNodeId=this.setNodeId;while(pos=0)break;data[pos]=best;setNodeId(best,pos);pos=left}data[pos]=item;setNodeId(item,pos)}}},{}],2:[function(require,module,exports){module.exports=aStarBi;var NodeHeap=require("./NodeHeap");var makeSearchStatePool=require("./makeSearchStatePool");var heuristics=require("./heuristics");var defaultSettings=require("./defaultSettings");var BY_FROM=1;var BY_TO=2;var NO_PATH=defaultSettings.NO_PATH;module.exports.l2=heuristics.l2;module.exports.l1=heuristics.l1;function aStarBi(graph,options){options=options||{};var oriented=options.oriented;var blocked=options.blocked;if(!blocked)blocked=defaultSettings.blocked;var heuristic=options.heuristic;if(!heuristic)heuristic=defaultSettings.heuristic;var distance=options.distance;if(!distance)distance=defaultSettings.distance;var pool=makeSearchStatePool();return{find:find};function find(fromId,toId){var from=graph.getNode(fromId);if(!from)throw new Error("fromId is not defined in this graph: "+fromId);var to=graph.getNode(toId);if(!to)throw new Error("toId is not defined in this graph: "+toId);if(from===to)return[from];pool.reset();var callVisitor=oriented?orientedVisitor:nonOrientedVisitor;var nodeState=new Map;var openSetFrom=new NodeHeap({compare:defaultSettings.compareFScore,setNodeId:defaultSettings.setHeapIndex});var openSetTo=new NodeHeap({compare:defaultSettings.compareFScore,setNodeId:defaultSettings.setHeapIndex});var startNode=pool.createNewState(from);nodeState.set(fromId,startNode);startNode.fScore=heuristic(from,to);startNode.distanceToSource=0;openSetFrom.push(startNode);startNode.open=BY_FROM;var endNode=pool.createNewState(to);endNode.fScore=heuristic(to,from);endNode.distanceToSource=0;openSetTo.push(endNode);endNode.open=BY_TO;var lMin=Number.POSITIVE_INFINITY;var minFrom;var minTo;var currentSet=openSetFrom;var currentOpener=BY_FROM;while(openSetFrom.length>0&&openSetTo.length>0){if(openSetFrom.lengthlMin)continue;graph.forEachLinkedNode(current.node.id,callVisitor);if(minFrom&&minTo){return reconstructBiDirectionalPath(minFrom,minTo)}}return NO_PATH;function nonOrientedVisitor(otherNode,link){return visitNode(otherNode,link,current)}function orientedVisitor(otherNode,link){if(currentOpener===BY_FROM){if(link.fromId===current.node.id)return visitNode(otherNode,link,current)}else if(currentOpener===BY_TO){if(link.toId===current.node.id)return visitNode(otherNode,link,current)}}function canExit(currentNode){var opener=currentNode.open;if(opener&&opener!==currentOpener){return true}return false}function reconstructBiDirectionalPath(a,b){var pathOfNodes=[];var aParent=a;while(aParent){pathOfNodes.push(aParent.node);aParent=aParent.parent}var bParent=b;while(bParent){pathOfNodes.unshift(bParent.node);bParent=bParent.parent}return pathOfNodes}function visitNode(otherNode,link,cameFrom){var otherSearchState=nodeState.get(otherNode.id);if(!otherSearchState){otherSearchState=pool.createNewState(otherNode);nodeState.set(otherNode.id,otherSearchState)}if(otherSearchState.closed){return}if(blocked(otherSearchState.node,cameFrom.node,link)){return}if(canExit(otherSearchState,cameFrom)){var potentialLMin=otherSearchState.distanceToSource+cameFrom.distanceToSource;if(potentialLMin=otherSearchState.distanceToSource){return}var target=currentOpener===BY_FROM?to:from;var newFScore=tentativeDistance+heuristic(otherSearchState.node,target);if(newFScore>=lMin){return}otherSearchState.fScore=newFScore;if(otherSearchState.open===0){currentSet.push(otherSearchState);currentSet.updateItem(otherSearchState.heapIndex);otherSearchState.open=currentOpener}otherSearchState.parent=cameFrom;otherSearchState.distanceToSource=tentativeDistance}}}},{"./NodeHeap":1,"./defaultSettings":4,"./heuristics":5,"./makeSearchStatePool":6}],3:[function(require,module,exports){module.exports=aStarPathSearch;var NodeHeap=require("./NodeHeap");var makeSearchStatePool=require("./makeSearchStatePool");var heuristics=require("./heuristics");var defaultSettings=require("./defaultSettings.js");var NO_PATH=defaultSettings.NO_PATH;module.exports.l2=heuristics.l2;module.exports.l1=heuristics.l1;function aStarPathSearch(graph,options){options=options||{};var oriented=options.oriented;var blocked=options.blocked;if(!blocked)blocked=defaultSettings.blocked;var heuristic=options.heuristic;if(!heuristic)heuristic=defaultSettings.heuristic;var distance=options.distance;if(!distance)distance=defaultSettings.distance;var pool=makeSearchStatePool();return{find:find};function find(fromId,toId){var from=graph.getNode(fromId);if(!from)throw new Error("fromId is not defined in this graph: "+fromId);var to=graph.getNode(toId);if(!to)throw new Error("toId is not defined in this graph: "+toId);pool.reset();var nodeState=new Map;var openSet=new NodeHeap({compare:defaultSettings.compareFScore,setNodeId:defaultSettings.setHeapIndex});var startNode=pool.createNewState(from);nodeState.set(fromId,startNode);startNode.fScore=heuristic(from,to);startNode.distanceToSource=0;openSet.push(startNode);startNode.open=1;var cameFrom;while(openSet.length>0){cameFrom=openSet.pop();if(goalReached(cameFrom,to))return reconstructPath(cameFrom);cameFrom.closed=true;graph.forEachLinkedNode(cameFrom.node.id,visitNeighbour,oriented)}return NO_PATH;function visitNeighbour(otherNode,link){var otherSearchState=nodeState.get(otherNode.id);if(!otherSearchState){otherSearchState=pool.createNewState(otherNode);nodeState.set(otherNode.id,otherSearchState)}if(otherSearchState.closed){return}if(otherSearchState.open===0){openSet.push(otherSearchState);otherSearchState.open=1}if(blocked(otherNode,cameFrom.node,link)){return}var tentativeDistance=cameFrom.distanceToSource+distance(otherNode,cameFrom.node,link);if(tentativeDistance>=otherSearchState.distanceToSource){return}otherSearchState.parent=cameFrom;otherSearchState.distanceToSource=tentativeDistance;otherSearchState.fScore=tentativeDistance+heuristic(otherSearchState.node,to);openSet.updateItem(otherSearchState.heapIndex)}}}function goalReached(searchState,targetNode){return searchState.node===targetNode}function reconstructPath(searchState){var path=[searchState.node];var parent=searchState.parent;while(parent){path.push(parent.node);parent=parent.parent}return path}},{"./NodeHeap":1,"./defaultSettings.js":4,"./heuristics":5,"./makeSearchStatePool":6}],4:[function(require,module,exports){var NO_PATH=[];if(typeof Object.freeze==="function")Object.freeze(NO_PATH);module.exports={heuristic:blindHeuristic,distance:constantDistance,blocked:neverBlocked,compareFScore:compareFScore,NO_PATH:NO_PATH,setHeapIndex:setHeapIndex,setH1:setH1,setH2:setH2,compareF1Score:compareF1Score,compareF2Score:compareF2Score};function blindHeuristic(){return 0}function constantDistance(){return 1}function neverBlocked(){return false}function compareFScore(a,b){var result=a.fScore-b.fScore;return result}function setHeapIndex(nodeSearchState,heapIndex){nodeSearchState.heapIndex=heapIndex}function compareF1Score(a,b){return a.f1-b.f1}function compareF2Score(a,b){return a.f2-b.f2}function setH1(node,heapIndex){node.h1=heapIndex}function setH2(node,heapIndex){node.h2=heapIndex}},{}],5:[function(require,module,exports){module.exports={l2:l2,l1:l1};function l2(a,b){var dx=a.x-b.x;var dy=a.y-b.y;return Math.sqrt(dx*dx+dy*dy)}function l1(a,b){var dx=a.x-b.x;var dy=a.y-b.y;return Math.abs(dx)+Math.abs(dy)}},{}],6:[function(require,module,exports){function NodeSearchState(node){this.node=node;this.parent=null;this.closed=false;this.open=0;this.distanceToSource=Number.POSITIVE_INFINITY;this.fScore=Number.POSITIVE_INFINITY;this.heapIndex=-1}function makeSearchStatePool(){var currentInCache=0;var nodeCache=[];return{createNewState:createNewState,reset:reset};function reset(){currentInCache=0}function createNewState(node){var cached=nodeCache[currentInCache];if(cached){cached.node=node;cached.parent=null;cached.closed=false;cached.open=0;cached.distanceToSource=Number.POSITIVE_INFINITY;cached.fScore=Number.POSITIVE_INFINITY;cached.heapIndex=-1}else{cached=new NodeSearchState(node);nodeCache[currentInCache]=cached}currentInCache++;return cached}}module.exports=makeSearchStatePool},{}],7:[function(require,module,exports){module.exports=nba;var NodeHeap=require("../NodeHeap");var heuristics=require("../heuristics");var defaultSettings=require("../defaultSettings.js");var makeNBASearchStatePool=require("./makeNBASearchStatePool.js");var NO_PATH=defaultSettings.NO_PATH;module.exports.l2=heuristics.l2;module.exports.l1=heuristics.l1;function nba(graph,options){options=options||{};var oriented=options.oriented;var quitFast=options.quitFast;var blocked=options.blocked;if(!blocked)blocked=defaultSettings.blocked;var heuristic=options.heuristic;if(!heuristic)heuristic=defaultSettings.heuristic;var distance=options.distance;if(!distance)distance=defaultSettings.distance;var pool=makeNBASearchStatePool();return{find:find};function find(fromId,toId){var from=graph.getNode(fromId);if(!from)throw new Error("fromId is not defined in this graph: "+fromId);var to=graph.getNode(toId);if(!to)throw new Error("toId is not defined in this graph: "+toId);pool.reset();var forwardVisitor=oriented?visitN1Oriented:visitN1;var reverseVisitor=oriented?visitN2Oriented:visitN2;var nodeState=new Map;var open1Set=new NodeHeap({compare:defaultSettings.compareF1Score,setNodeId:defaultSettings.setH1});var open2Set=new NodeHeap({compare:defaultSettings.compareF2Score,setNodeId:defaultSettings.setH2});var minNode;var lMin=Number.POSITIVE_INFINITY;var startNode=pool.createNewState(from);nodeState.set(fromId,startNode);startNode.g1=0;var f1=heuristic(from,to);startNode.f1=f1;open1Set.push(startNode);var endNode=pool.createNewState(to);nodeState.set(toId,endNode);endNode.g2=0;var f2=f1;endNode.f2=f2;open2Set.push(endNode);var cameFrom;while(open2Set.length&&open1Set.length){if(open1Set.length0){f1=open1Set.peek().f1}}function reverseSearch(){cameFrom=open2Set.pop();if(cameFrom.closed){return}cameFrom.closed=true;if(cameFrom.f20){f2=open2Set.peek().f2}}function visitN1(otherNode,link){var otherSearchState=nodeState.get(otherNode.id);if(!otherSearchState){otherSearchState=pool.createNewState(otherNode);nodeState.set(otherNode.id,otherSearchState)}if(otherSearchState.closed)return;if(blocked(cameFrom.node,otherNode,link))return;var tentativeDistance=cameFrom.g1+distance(cameFrom.node,otherNode,link);if(tentativeDistance0){for(var i=this.length>>1;i>=0;i--)this._down(i)}if(options.setNodeId){for(var i=0;i0){this.data[0]=this.data[this.length];this.setNodeId(this.data[0],0);this._down(0)}this.data.pop();return top},peek:function(){return this.data[0]},updateItem:function(pos){this._down(pos);this._up(pos)},_up:function(pos){var data=this.data;var compare=this.compare;var setNodeId=this.setNodeId;var item=data[pos];while(pos>0){var parent=pos-1>>1;var current=data[parent];if(compare(item,current)>=0)break;data[pos]=current;setNodeId(current,pos);pos=parent}data[pos]=item;setNodeId(item,pos)},_down:function(pos){var data=this.data;var compare=this.compare;var halfLength=this.length>>1;var item=data[pos];var setNodeId=this.setNodeId;while(pos=0)break;data[pos]=best;setNodeId(best,pos);pos=left}data[pos]=item;setNodeId(item,pos)}}},{}],2:[function(require,module,exports){module.exports=aStarBi;var NodeHeap=require("./NodeHeap");var makeSearchStatePool=require("./makeSearchStatePool");var heuristics=require("./heuristics");var defaultSettings=require("./defaultSettings");var BY_FROM=1;var BY_TO=2;var NO_PATH=defaultSettings.NO_PATH;module.exports.l2=heuristics.l2;module.exports.l1=heuristics.l1;function aStarBi(graph,options){options=options||{};var oriented=options.oriented;var blocked=options.blocked;if(!blocked)blocked=defaultSettings.blocked;var heuristic=options.heuristic;if(!heuristic)heuristic=defaultSettings.heuristic;var distance=options.distance;if(!distance)distance=defaultSettings.distance;var pool=makeSearchStatePool();return{find:find};function find(fromId,toId){var from=graph.getNode(fromId);if(!from)throw new Error("fromId is not defined in this graph: "+fromId);var to=graph.getNode(toId);if(!to)throw new Error("toId is not defined in this graph: "+toId);if(from===to)return[from];pool.reset();var callVisitor=oriented?orientedVisitor:nonOrientedVisitor;var nodeState=new Map;var openSetFrom=new NodeHeap({compare:defaultSettings.compareFScore,setNodeId:defaultSettings.setHeapIndex});var openSetTo=new NodeHeap({compare:defaultSettings.compareFScore,setNodeId:defaultSettings.setHeapIndex});var startNode=pool.createNewState(from);nodeState.set(fromId,startNode);startNode.fScore=heuristic(from,to);startNode.distanceToSource=0;openSetFrom.push(startNode);startNode.open=BY_FROM;var endNode=pool.createNewState(to);endNode.fScore=heuristic(to,from);endNode.distanceToSource=0;openSetTo.push(endNode);endNode.open=BY_TO;var lMin=Number.POSITIVE_INFINITY;var minFrom;var minTo;var currentSet=openSetFrom;var currentOpener=BY_FROM;while(openSetFrom.length>0&&openSetTo.length>0){if(openSetFrom.lengthlMin)continue;graph.forEachLinkedNode(current.node.id,callVisitor);if(minFrom&&minTo){return reconstructBiDirectionalPath(minFrom,minTo)}}return NO_PATH;function nonOrientedVisitor(otherNode,link){return visitNode(otherNode,link,current)}function orientedVisitor(otherNode,link){if(currentOpener===BY_FROM){if(link.fromId===current.node.id)return visitNode(otherNode,link,current)}else if(currentOpener===BY_TO){if(link.toId===current.node.id)return visitNode(otherNode,link,current)}}function canExit(currentNode){var opener=currentNode.open;if(opener&&opener!==currentOpener){return true}return false}function reconstructBiDirectionalPath(a,b){var pathOfNodes=[];var aParent=a;while(aParent){pathOfNodes.push(aParent.node);aParent=aParent.parent}var bParent=b;while(bParent){pathOfNodes.unshift(bParent.node);bParent=bParent.parent}return pathOfNodes}function visitNode(otherNode,link,cameFrom){var otherSearchState=nodeState.get(otherNode.id);if(!otherSearchState){otherSearchState=pool.createNewState(otherNode);nodeState.set(otherNode.id,otherSearchState)}if(otherSearchState.closed){return}if(blocked(otherSearchState.node,cameFrom.node,link)){return}if(canExit(otherSearchState,cameFrom)){var potentialLMin=otherSearchState.distanceToSource+cameFrom.distanceToSource;if(potentialLMin=otherSearchState.distanceToSource){return}var target=currentOpener===BY_FROM?to:from;var newFScore=tentativeDistance+heuristic(otherSearchState.node,target);if(newFScore>=lMin){return}otherSearchState.fScore=newFScore;if(otherSearchState.open===0){currentSet.push(otherSearchState);currentSet.updateItem(otherSearchState.heapIndex);otherSearchState.open=currentOpener}otherSearchState.parent=cameFrom;otherSearchState.distanceToSource=tentativeDistance}}}},{"./NodeHeap":1,"./defaultSettings":4,"./heuristics":5,"./makeSearchStatePool":6}],3:[function(require,module,exports){module.exports=aStarPathSearch;var NodeHeap=require("./NodeHeap");var makeSearchStatePool=require("./makeSearchStatePool");var heuristics=require("./heuristics");var defaultSettings=require("./defaultSettings.js");var NO_PATH=defaultSettings.NO_PATH;module.exports.l2=heuristics.l2;module.exports.l1=heuristics.l1;function aStarPathSearch(graph,options){options=options||{};var oriented=options.oriented;var blocked=options.blocked;if(!blocked)blocked=defaultSettings.blocked;var heuristic=options.heuristic;if(!heuristic)heuristic=defaultSettings.heuristic;var distance=options.distance;if(!distance)distance=defaultSettings.distance;var pool=makeSearchStatePool();return{find:find};function find(fromId,toId){var from=graph.getNode(fromId);if(!from)throw new Error("fromId is not defined in this graph: "+fromId);var to=graph.getNode(toId);if(!to)throw new Error("toId is not defined in this graph: "+toId);pool.reset();var nodeState=new Map;var openSet=new NodeHeap({compare:defaultSettings.compareFScore,setNodeId:defaultSettings.setHeapIndex});var startNode=pool.createNewState(from);nodeState.set(fromId,startNode);startNode.fScore=heuristic(from,to);startNode.distanceToSource=0;openSet.push(startNode);startNode.open=1;var cameFrom;while(openSet.length>0){cameFrom=openSet.pop();if(goalReached(cameFrom,to))return reconstructPath(cameFrom);cameFrom.closed=true;graph.forEachLinkedNode(cameFrom.node.id,visitNeighbour,oriented)}return NO_PATH;function visitNeighbour(otherNode,link){var otherSearchState=nodeState.get(otherNode.id);if(!otherSearchState){otherSearchState=pool.createNewState(otherNode);nodeState.set(otherNode.id,otherSearchState)}if(otherSearchState.closed){return}if(otherSearchState.open===0){openSet.push(otherSearchState);otherSearchState.open=1}if(blocked(otherNode,cameFrom.node,link)){return}var tentativeDistance=cameFrom.distanceToSource+distance(otherNode,cameFrom.node,link,cameFrom.parent&&cameFrom.parent.node);if(tentativeDistance>=otherSearchState.distanceToSource){return}otherSearchState.parent=cameFrom;otherSearchState.distanceToSource=tentativeDistance;otherSearchState.fScore=tentativeDistance+heuristic(otherSearchState.node,to);openSet.updateItem(otherSearchState.heapIndex)}}}function goalReached(searchState,targetNode){return searchState.node===targetNode}function reconstructPath(searchState){var path=[searchState.node];var parent=searchState.parent;while(parent){path.push(parent.node);parent=parent.parent}return path}},{"./NodeHeap":1,"./defaultSettings.js":4,"./heuristics":5,"./makeSearchStatePool":6}],4:[function(require,module,exports){var NO_PATH=[];if(typeof Object.freeze==="function")Object.freeze(NO_PATH);module.exports={heuristic:blindHeuristic,distance:constantDistance,blocked:neverBlocked,compareFScore:compareFScore,NO_PATH:NO_PATH,setHeapIndex:setHeapIndex,setH1:setH1,setH2:setH2,compareF1Score:compareF1Score,compareF2Score:compareF2Score};function blindHeuristic(){return 0}function constantDistance(){return 1}function neverBlocked(){return false}function compareFScore(a,b){var result=a.fScore-b.fScore;return result}function setHeapIndex(nodeSearchState,heapIndex){nodeSearchState.heapIndex=heapIndex}function compareF1Score(a,b){return a.f1-b.f1}function compareF2Score(a,b){return a.f2-b.f2}function setH1(node,heapIndex){node.h1=heapIndex}function setH2(node,heapIndex){node.h2=heapIndex}},{}],5:[function(require,module,exports){module.exports={l2:l2,l1:l1};function l2(a,b){var dx=a.x-b.x;var dy=a.y-b.y;return Math.sqrt(dx*dx+dy*dy)}function l1(a,b){var dx=a.x-b.x;var dy=a.y-b.y;return Math.abs(dx)+Math.abs(dy)}},{}],6:[function(require,module,exports){function NodeSearchState(node){this.node=node;this.parent=null;this.closed=false;this.open=0;this.distanceToSource=Number.POSITIVE_INFINITY;this.fScore=Number.POSITIVE_INFINITY;this.heapIndex=-1}function makeSearchStatePool(){var currentInCache=0;var nodeCache=[];return{createNewState:createNewState,reset:reset};function reset(){currentInCache=0}function createNewState(node){var cached=nodeCache[currentInCache];if(cached){cached.node=node;cached.parent=null;cached.closed=false;cached.open=0;cached.distanceToSource=Number.POSITIVE_INFINITY;cached.fScore=Number.POSITIVE_INFINITY;cached.heapIndex=-1}else{cached=new NodeSearchState(node);nodeCache[currentInCache]=cached}currentInCache++;return cached}}module.exports=makeSearchStatePool},{}],7:[function(require,module,exports){module.exports=nba;var NodeHeap=require("../NodeHeap");var heuristics=require("../heuristics");var defaultSettings=require("../defaultSettings.js");var makeNBASearchStatePool=require("./makeNBASearchStatePool.js");var NO_PATH=defaultSettings.NO_PATH;module.exports.l2=heuristics.l2;module.exports.l1=heuristics.l1;function nba(graph,options){options=options||{};var oriented=options.oriented;var quitFast=options.quitFast;var blocked=options.blocked;if(!blocked)blocked=defaultSettings.blocked;var heuristic=options.heuristic;if(!heuristic)heuristic=defaultSettings.heuristic;var distance=options.distance;if(!distance)distance=defaultSettings.distance;var pool=makeNBASearchStatePool();return{find:find};function find(fromId,toId){var from=graph.getNode(fromId);if(!from)throw new Error("fromId is not defined in this graph: "+fromId);var to=graph.getNode(toId);if(!to)throw new Error("toId is not defined in this graph: "+toId);pool.reset();var forwardVisitor=oriented?visitN1Oriented:visitN1;var reverseVisitor=oriented?visitN2Oriented:visitN2;var nodeState=new Map;var open1Set=new NodeHeap({compare:defaultSettings.compareF1Score,setNodeId:defaultSettings.setH1});var open2Set=new NodeHeap({compare:defaultSettings.compareF2Score,setNodeId:defaultSettings.setH2});var minNode;var lMin=Number.POSITIVE_INFINITY;var startNode=pool.createNewState(from);nodeState.set(fromId,startNode);startNode.g1=0;var f1=heuristic(from,to);startNode.f1=f1;open1Set.push(startNode);var endNode=pool.createNewState(to);nodeState.set(toId,endNode);endNode.g2=0;var f2=f1;endNode.f2=f2;open2Set.push(endNode);var cameFrom;while(open2Set.length&&open1Set.length){if(open1Set.length0){f1=open1Set.peek().f1}}function reverseSearch(){cameFrom=open2Set.pop();if(cameFrom.closed){return}cameFrom.closed=true;if(cameFrom.f20){f2=open2Set.peek().f2}}function visitN1(otherNode,link){var otherSearchState=nodeState.get(otherNode.id);if(!otherSearchState){otherSearchState=pool.createNewState(otherNode);nodeState.set(otherNode.id,otherSearchState)}if(otherSearchState.closed)return;if(blocked(cameFrom.node,otherNode,link))return;var tentativeDistance=cameFrom.g1+distance(cameFrom.node,otherNode,link,cameFrom.p1&&cameFrom.p1.node);if(tentativeDistance, to: Node) => number - distance?: (from: Node, to: Node, link: Link) => number + distance?: (from: Node, to: Node, link: Link, parent: Node | null) => number blocked?: (from: Node, to: Node, link: Link) => boolean }