I want to find a fast path.(AStar Algorithm) - a-star

there is my astar algorithm
while (!find || open.Count > 0)
{
Vector2 current = LowestF(Start, open, Destination);
if (current == Destination)
{
find = true;
break;
}
close.Add(current);
open.Remove(current);
List<Vector2> adjacent = MoveDirection(current);
lowF = int.MaxValue;
for (int i = 0; i < adjacent.Count; i++)
{
if (close.Contains(adjacent[i]))
continue;
if(getF(Start, adjacent[i], Destination) < lowF)
{
lowF = getF(Start, adjacent[i], Destination);
lowV = adjacent[i];
}
if (!open.Contains(adjacent[i]))
{
open.Add(adjacent[i]);
}
yield return new WaitForSeconds(0.0125f);
}
}
But I can't get a fast track. What should I do to get a quick route?
If a node is required, the Node has Parent and Pos.
I want a simple code.
result
result

Related

Getting Illegal Instruction:4

I was trying to do this function in C but for some reason is giving me "Illegal instruction: 4"... From what I looked up it may be because I'm using iOs, but still I'm using VSCode and not a project so I have no idea how to correct it.
The function is the following:
void divideSocios(void){
int i;
for (i = 0; i < MAXFILA || socios[i].next != -1; i++){
if (socios[i].sc.pago >= 50){
if (semDiv[0].next == 0){
semDiv[0].next = -1;
semDiv[0].sc.id = socios[i].sc.id;
semDiv[0].sc.pago = socios[i].sc.pago;
strcpy(semDiv[0].sc.nome, socios[i].sc.nome);
}
else{
for (; i < MAXFILA && semDiv[i].next != -1; i++);
semDiv[i-1].next = i;
semDiv[i].next = -1;
semDiv[i].sc.pago = socios[i].sc.pago;
semDiv[i].sc.id = socios[i].sc.id;
strcpy(semDiv[i].sc.nome, socios[i].sc.nome);
}
} else {
if (comDiv[0].next == 0){
comDiv[0].next = -1;
comDiv[0].sc.id = socios[i].sc.id;
comDiv[0].sc.pago = socios[i].sc.pago;
strcpy(comDiv[0].sc.nome, socios[i].sc.nome);
}
else{
for (; i < MAXFILA && comDiv[i].next != -1; i++);
comDiv[i-1].next = i;
comDiv[i].next = -1;
comDiv[i].sc.pago = socios[i].sc.pago;
comDiv[i].sc.id = socios[i].sc.id;
strcpy(comDiv[i].sc.nome, socios[i].sc.nome);
}
}
}
}
I basically have 3 different linked lists by matrix, each node with a struct and the index of the current node, and depending on the "pago" atribute from the struct of the node I want to separate them from the original list between the other 2.

More than 100 points and one polyline, Google Maps v3

I'm working with google maps api v3 and I'm trying to use snap to road with more than 100 points but in addition end up with just one polyline with the whole route that I can put a small animation. The view is a html.erb.
var apiKey = any_key;
var map = handler.getMap();
var drawingManager;
var placeIdArray = [];
var snappedCoordinates = [];
var path = <%= raw(#locations) %>
var markers = <%= raw(#markers) %>
var centerOn = path[0].split(',');
function breadCrumbsGrapher(path) {
handler.removeMarkers(Gmaps.store.markers);
for(var i = 0; i < polylines.length; i++) {
polylines[i].setMap(null);
}
var divided = handlePath(path);
if (typeof divided[0] == 'object') {
for(var i = 0; i < divided.length; i++) {
runSnapToRoad(divided[i]);
}
} else {
runSnapToRoad(path);
}
}
function waypointsLimiter(path) {
var path_loc_size = path.length;
var limited = [];
if(path_loc_size > 30) {
var stepper = Math.ceil(path_loc_size/30);
for(var i = stepper; i < path_loc_size; i += stepper) {
limited.push(path[i]);
}
if(limited.indexOf(path[path_loc_size-1]) == -1) {
limited.push(path[path_loc_size-1]);
}
} else {
limited = path;
}
return limited;
}
function handlePath(path) {
var i = 0;
var j = path.length;
if (j > 100) {
var newArray = [],
chunk = j/2;
if (j >= 200) {
chunk = j/3;
} else if (j >= 300) {
chunk = j/4;
} else if (j >= 400) {
chunk = j/5;
} else if (j >= 500 ) {
chunk = j/6;
} else if (j >= 600) {
chunk = j/7;
} else if (j >= 700 || j <= 799) {
chunk = j/8;
} else {
alert('La ruta no puede ser mostrada');
}
for (i, j; i < j; i+=chunk) {
newArray.push(path.slice(i,i+chunk+1));
}
return newArray;
} else {
return path;
}
}
// Snap a user-created polyline to roads and draw the snapped path
function runSnapToRoad(path) {
var path = path.join('|');
$.get('https://roads.googleapis.com/v1/snapToRoads', {
interpolate: true,
key: apiKey,
path: path,
}, function(data) {
processSnapToRoadResponse(data);
drawSnappedPolyline();
});
}
// Store snapped polyline returned by the snap-to-road service.
function processSnapToRoadResponse(data) {
snappedCoordinates = [];
placeIdArray = [];
for (var i = 0; i < data.snappedPoints.length; i++) {
var latlng = new google.maps.LatLng(
data.snappedPoints[i].location.latitude,
data.snappedPoints[i].location.longitude);
snappedCoordinates.push(latlng);
placeIdArray.push(data.snappedPoints[i].placeId);
}
}
// Draws the snapped polyline (after processing snap-to-road response).
function drawSnappedPolyline() {
var symbol = {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
scale: 3,
strokeColor: '#3B16B3'
};
var snappedPolyline = new google.maps.Polyline({
path: snappedCoordinates,
strokeColor: '#E51E25',
strokeWeight: 3,
icons: [{
icon: symbol,
offset: '0%'
}]
});
snappedPolyline.setMap(map);
animate(snappedPolyline);
zoomToObject(snappedPolyline);
polylines.push(snappedPolyline);
}
function zoomToObject(obj){
var bounds = new google.maps.LatLngBounds();
var points = obj.getPath().getArray();
for (var n = 0; n < points.length ; n++){
bounds.extend(points[n]);
}
map.fitBounds(bounds);
}
function animate(line) {
var count = 0;
window.setInterval(function() {
count = (count + 1) % 600;
var icons = line.get('icons');
icons[0].offset = (count / 6) + '%';
line.set('icons', icons);
}, 70);
}
breadCrumbsGrapher(path);
Also I've tried declaring a variable outside so I can concat all of the coordinates and generate a polyline with it but doesn't seem to work. Actualy that big array ends up being of 2000+ points.
The result that I have with the provided code
After all of that the issue is that I don't know how to merge the polylines to have just one line and being able to animate just that one line. If there's more than 100 coordinates I plot more polylines. In the image you can see that there's 3 icons (one for each polyline) and I need just to draw one line and have 1 icon.
To reproduce the issue just add a key and if you want use this set of coordinates:
https://drive.google.com/file/d/1jLb7Djv5DiSdR3k4QZRSatXBwrohlxcI/view?usp=sharing
function breadCrumbsGrapher(path) {
//mapMarkers();
snappedCoordinates = [];
handler.removeMarkers(Gmaps.store.markers);
for(var i = 0; i < polylines.length; i++) {
polylines[i].setMap(null);
}
var divided = handlePath(path);
if (typeof divided[0] == 'object') {
for(var i = 0; i < divided.length; i++) {
runSnapToRoad(divided[i]);
}
} else {
runSnapToRoad(path);
}
console.log(snappedCoordinates);
drawSnappedPolyline();
}
function runSnapToRoad(path) {
var path = path.join('|');
$.get('https://roads.googleapis.com/v1/snapToRoads', {
interpolate: true,
key: apiKey,
path: path,
}, function(data) {
processSnapToRoadResponse(data);
//drawSnappedPolyline();
});
}
I've changed the code but it doesn't work, even though I end up with a 2,557 coordinates array.
I've tried also tried this thinking that this could give me the time to have all coordinates:
async function breadCrumbsGrapher(path) {
//mapMarkers();
snappedCoordinates = [];
handler.removeMarkers(Gmaps.store.markers);
for(var i = 0; i < polylines.length; i++) {
polylines[i].setMap(null);
}
var divided = handlePath(path);
if (typeof divided[0] == 'object') {
for(var i = 0; i < divided.length; i++) {
await runSnapToRoad(divided[i]);
}
} else {
await runSnapToRoad(path);
}
console.log(snappedCoordinates);
drawSnappedPolyline();
}
and:
async function runSnapToRoad(path) {
var path = path.join('|');
await $.get('https://roads.googleapis.com/v1/snapToRoads', {
interpolate: true,
key: apiKey,
path: path,
}, function(data) {
processSnapToRoadResponse(data);
});
}
Thank you in advance.
You are using $.get() to query the Roads API which is an asynchronous call so when you call drawSnappedPolyline() from within your breadCrumbsGrapher function, you most probably don't (yet) have all coordinates in return from your AJAX call(s).
If you have 550 coordinates in your original path, you then know you must call the Roads API 6 times (5 times with 100 points + 1 time with 50 points). You should then be able to set a counter somewhere, to only draw your (complete) Polyline, once you got your 6 responses from the Roads API.
Or you could base that on the length of your final array (compared to the original path) although I don't know what would happen in case some points can't be "snapped".

XF how to lock focus on entry in iOS?

I have some entries in my app which contain some numbers and I have a button that when I click on the button it adds one unit to the number in the entry that is focused, but the problem is that when i click the button, the entry loses the focus and keyboard disappears, although I want the entry to be focused, I found a solution for Android, but couldn't find anything for iOS!!
Does anybody know what to do? I don't want the entry to lose focus
Update:
private void StepUpButton_Clicked(object sender, EventArgs e)
{
double value;
for (int i = 0; i < 30; i++)
{
if (GetEntries(i).IsFocused)
{
if (String.IsNullOrEmpty(GetEntries(i).Text) || GetEntries(i).Text.Equals("-"))
{
value = 0.00;
}
else
{
value = Convert.ToDouble(GetEntries(i).Text);
}
for (int j = 0; j < 10; j++)
{
if (GetEntries(i) == GetVa1ToVb1Amp(j))
{
GetVa1ToVb1Amp(j).Text = controller.StepUpClicked(0, value).ToString("F2");
}
if (GetEntries(i) == GetIa1ToIb3Amp(j))
{
GetIa1ToIb3Amp(j).Text = controller.StepUpClicked(1, value).ToString("F3");
}
if (GetEntries(i) == GetVa1ToIb3Phase(j))
{
GetVa1ToIb3Phase(j).Text = controller.StepUpClicked(2, value).ToString("F2");
}
if (GetEntries(i) == GetVa1ToIb3Freq(j))
{
GetVa1ToIb3Freq(j).Text = controller.StepUpClicked(3, value).ToString("F3");
}
}
}
}
}

A star algorithm with multiple goals [duplicate]

Let's consider a simple grid, where any point is connected with at most 4 other points (North-East-West-South neighborhood).
I have to write program, that computes minimal route from selected initial point to any of goal points, which are connected (there is route consisting of goal points between any two goals). Of course there can be obstacles on grid.
My solution is quite simple: I'm using A* algorithm with variable heuristic function h(x) - manhattan distance from x to nearest goal point. To find nearest goal point I have to do linear search (in O(n), where n - number of goal points). Here is my question: is there any more efficient solution (heuristic function) to dynamically find nearest goal point (where time < O(n))?
Or maybe A* is not good way to solve that problem?
How many goals, tens or thousands? If tens your way will work fine, if thousands then nearest neighbor search will give you ideas on setting up your data to search quickly.
The tradeoffs are obvious, spatially organizing your data to search will take time and on small sets brute force will be simpler to maintain. Since you're constantly evaluating I think that structuring the data will be worthwhile at very low numbers of points.
An alternate way to do this would be a modified flood fill algorithm that stops once it reaches a destination point during the flood.
First, decide whether you need to optimize, because any optimization is going to complicate your code, and for a small number of goals, your current solution is probably fine for a simple heuristic like Manhattan distance.
Before taking the first step, compute the heuristic for each goal. Remember the nearest goal as the currently selected goal, and move toward it, but subtract the maximum possible progress toward any goal from all the other distances. You can consider this second value a "meta-heuristic"; it is an optimistic estimate of the heuristic for other goals.
On subsequent steps, compute the heuristic for the current goal, and any goals with a "meta-heuristic" that is less than or equal to the heuristic. The other goals can't possibly have a better heuristic, so you don't need to compute them. The nearest goal becomes the new current goal; move toward it, subtracting the maximum possible progress from the others. Repeat until you arrive at a goal.
Use Dijkstra's algorithm, which has as it's output the minimal cost to all reachable points. Then you just select the goal points from the output.
you may consider this article If your goals not too much and want simple ways
If you want to search for any of several goals, construct a heuristic
h'(x) that is the minimum of h1(x), h2(x), h3(x), ... where h1, h2, h3
are heuristics to each of the nearby spots.
One way to think about this is that we can add a new zero-cost edge
from each of the goals to a new graph node. A path to that new node
will necessarily go through one of the goal nodes.
If you want to search for paths to all of several goals, your best
option may be Dijkstra’s Algorithm with early exit when you find all
the goals. There may be a variant of A* that can calculate these
paths; I don’t know.
If you want to search for spot near a single goal, ask A* search to
find a path to the center of the goal area. While processing nodes
from the OPEN set, exit when you pull a node that is near enough.
You can calculate the f score using the nearest target. As others said, for naive approach, you can directly calculate all target distance from current node and pick the minimum, if you only have few targets to search. For more than 100 targets, you can probably find the nearest by KDTree to speed up the process.
Here is a sample code in dart.
Iterable<Vector2> getPath(Vector2 from, Iterable<Vector2> targets,
{double? maxDistance, bool useAStar = false}) {
targets = targets.asSet();
clearPoints();
var projectedTargets = addPoints(targets).toSet();
var tree = useAStar ? IKDTree(targets) : null;
var q = PriorityQueue<Node>(_priorityQueueComparor);
Map<Vector2, Node> visited = {};
var node = Node(from);
visited[from] = node;
q.add(node);
while (q.isNotEmpty) {
var current = q.removeFirst();
// developer.log(
// '${current.point}#${current.distance}: ${getEdges(current.point).map((e) => e.dest)}');
for (var edge in getEdges(current.point)) {
if (visited.containsKey(edge.dest)) continue;
var distance = current.distance + edge.distance;
// too far
if (maxDistance != null && distance > maxDistance) continue;
// it is a target
if (projectedTargets.contains(edge.dest)) {
return reconstructPath(visited, current, edge.dest);
}
// we only interested in exploring polygon node.
if (!_polygonPoints.contains(edge.dest)) continue;
var f = 0.0;
if (tree != null) {
var nearest = tree
.nearest(edge.dest, maxDistance: maxDistance ?? double.infinity)
.firstOrNull;
f = nearest != null ? edge.dest.distanceToSquared(nearest) : 0.0;
}
node = Node(edge.dest, distance, current.count + 1, current.point, f);
visited[edge.dest] = node;
q.add(node);
}
}
return [];
}
Iterable<Vector2> reconstructPath(
Map<Vector2, Node> visited, Node prev, Vector2 point) {
var path = <Vector2>[point];
Node? currentNode = prev;
while (currentNode != null) {
path.add(currentNode.point);
currentNode = visited[currentNode.prev];
}
return path.reversed;
}
int _priorityQueueComparor(Node p0, Node p1) {
int r;
if (p0.f > 0 && p1.f > 0) {
r = ((p0.distance * p0.distance) + p0.f)
.compareTo((p1.distance * p1.distance) + p1.f);
if (r != 0) return r;
}
r = p0.distance.compareTo(p1.distance);
if (r != 0) return r;
return p0.count.compareTo(p1.count);
}
and the implementation of KDTree
class IKDTree {
final int _dimensions = 2;
late Node? _root;
IKDTree(Iterable<Vector2> points) {
_root = _buildTree(points, null);
}
Node? _buildTree(Iterable<Vector2> points, Node? parent) {
var list = points.asList();
if (list.isEmpty) return null;
var median = (list.length / 2).floor();
// Select the longest dimension as division axis
var axis = 0;
var aabb = AABB.fromPoints(list);
for (var i = 1; i < _dimensions; i++) {
if (aabb.range[i] > aabb.range[axis]) {
axis = i;
}
}
// Divide by the division axis and recursively build.
// var list = list.orderBy((e) => _selector(e)[axis]).asList();
list.sort(((a, b) => a[axis].compareTo(b[axis])));
var point = list[median];
var node = Node(point.clone());
node.parent = parent;
node.left = _buildTree(list.sublist(0, median), node);
node.right = _buildTree(list.sublist(median + 1), node);
update(node);
return node;
}
void addPoint(Vector2 point, [bool allowRebuild = true]) {
_root = _addByPoint(_root, point, allowRebuild, 0);
}
// void removePoint(Vector2 point, [bool allowRebuild = true]) {
// if (node == null) return;
// _removeNode(node, allowRebuild);
// }
Node? _addByPoint(
Node? node, Vector2 point, bool allowRebuild, int parentDim) {
if (node == null) {
node = Node(point.clone());
node.dimension = (parentDim + 1) % _dimensions;
update(node);
return node;
}
_pushDown(node);
if (point[node.dimension] < node.point[node.dimension]) {
node.left = _addByPoint(node.left, point, allowRebuild, node.dimension);
} else {
node.right = _addByPoint(node.right, point, allowRebuild, node.dimension);
}
update(node);
bool needRebuild = allowRebuild && criterionCheck(node);
if (needRebuild) node = rebuild(node);
return node;
}
// checked
void _pushDown(Node? node) {
if (node == null) return;
if (node.needPushDownToLeft && node.left != null) {
node.left!.treeDownsampleDeleted |= node.treeDownsampleDeleted;
node.left!.pointDownsampleDeleted |= node.treeDownsampleDeleted;
node.left!.treeDeleted =
node.treeDeleted || node.left!.treeDownsampleDeleted;
node.left!.deleted =
node.left!.treeDeleted || node.left!.pointDownsampleDeleted;
if (node.treeDownsampleDeleted) {
node.left!.downDeletedNum = node.left!.treeSize;
}
if (node.treeDeleted) {
node.left!.invalidNum = node.left!.treeSize;
} else {
node.left!.invalidNum = node.left!.downDeletedNum;
}
node.left!.needPushDownToLeft = true;
node.left!.needPushDownToRight = true;
node.needPushDownToLeft = false;
}
if (node.needPushDownToRight && node.right != null) {
node.right!.treeDownsampleDeleted |= node.treeDownsampleDeleted;
node.right!.pointDownsampleDeleted |= node.treeDownsampleDeleted;
node.right!.treeDeleted =
node.treeDeleted || node.right!.treeDownsampleDeleted;
node.right!.deleted =
node.right!.treeDeleted || node.right!.pointDownsampleDeleted;
if (node.treeDownsampleDeleted) {
node.right!.downDeletedNum = node.right!.treeSize;
}
if (node.treeDeleted) {
node.right!.invalidNum = node.right!.treeSize;
} else {
node.right!.invalidNum = node.right!.downDeletedNum;
}
node.right!.needPushDownToLeft = true;
node.right!.needPushDownToRight = true;
node.needPushDownToRight = false;
}
}
void _removeNode(Node? node, bool allowRebuild) {
if (node == null || node.deleted) return;
_pushDown(node);
node.deleted = true;
node.invalidNum++;
if (node.invalidNum == node.treeSize) {
node.treeDeleted = true;
}
// update and rebuild parent
var parent = node.parent;
if (parent != null) {
updateAncestors(parent);
bool needRebuild = allowRebuild && criterionCheck(parent);
if (needRebuild) parent = rebuild(parent);
}
}
void updateAncestors(Node? node) {
if (node == null) return;
update(node);
updateAncestors(node.parent);
}
void _removeByPoint(Node? node, Vector2 point, bool allowRebuild) {
if (node == null || node.treeDeleted) return;
_pushDown(node);
if (node.point == point && !node.deleted) {
node.deleted = true;
node.invalidNum++;
if (node.invalidNum == node.treeSize) {
node.treeDeleted = true;
}
return;
}
if (point[node.dimension] < node.point[node.dimension]) {
_removeByPoint(node.left, point, false);
} else {
_removeByPoint(node.right, point, false);
}
update(node);
bool needRebuild = allowRebuild && criterionCheck(node);
if (needRebuild) rebuild(node);
}
// checked
void update(Node node) {
var left = node.left;
var right = node.right;
node.treeSize = (left != null ? left.treeSize : 0) +
(right != null ? right.treeSize : 0) +
1;
node.invalidNum = (left != null ? left.invalidNum : 0) +
(right != null ? right.invalidNum : 0) +
(node.deleted ? 1 : 0);
node.downDeletedNum = (left != null ? left.downDeletedNum : 0) +
(right != null ? right.downDeletedNum : 0) +
(node.pointDownsampleDeleted ? 1 : 0);
node.treeDownsampleDeleted = (left == null || left.treeDownsampleDeleted) &&
(right == null || right.treeDownsampleDeleted) &&
node.pointDownsampleDeleted;
node.treeDeleted = (left == null || left.treeDeleted) &&
(right == null || right.treeDeleted) &&
node.deleted;
var minList = <Vector2>[];
var maxList = <Vector2>[];
if (left != null && !left.treeDeleted) {
minList.add(left.aabb.min);
maxList.add(left.aabb.max);
}
if (right != null && !right.treeDeleted) {
minList.add(right.aabb.min);
maxList.add(right.aabb.max);
}
if (!node.deleted) {
minList.add(node.point);
maxList.add(node.point);
}
if (minList.isNotEmpty && maxList.isNotEmpty) {
node.aabb = AABB()
..min = minList.min()
..max = maxList.max();
}
// TODO: Radius data for search: https://github.com/hku-mars/ikd-Tree/blob/main/ikd-Tree/ikd_Tree.cpp#L1312
if (left != null) left.parent = node;
if (right != null) right.parent = node;
// TODO: root alpha value for multithread
}
// checked
final minimalUnbalancedTreeSize = 10;
final deleteCriterionParam = 0.3;
final balanceCriterionParam = 0.6;
bool criterionCheck(Node node) {
if (node.treeSize <= minimalUnbalancedTreeSize) return false;
double balanceEvaluation = 0.0;
double deleteEvaluation = 0.0;
var child = node.left ?? node.right!;
deleteEvaluation = node.invalidNum / node.treeSize;
balanceEvaluation = child.treeSize / (node.treeSize - 1);
if (deleteEvaluation > deleteCriterionParam) return true;
if (balanceEvaluation > balanceCriterionParam ||
balanceEvaluation < 1 - balanceCriterionParam) return true;
return false;
}
void rebuildAll() {
_root = rebuild(_root);
}
// checked
Node? rebuild(Node? node) {
if (node == null) return null;
var parent = node.parent;
var points = flatten(node).toList();
// log('rebuilding: $node objects: ${objects.length}');
deleteTreeNodes(node);
return _buildTree(points, parent);
// if (parent == null) {
// _root = newNode;
// } else if (parent.left == node) {
// parent.left = newNode;
// } else if (parent.right == node) {
// parent.right = newNode;
// }
}
// checked
Iterable<Vector2> flatten(Node? node) sync* {
if (node == null) return;
_pushDown(node);
if (!node.deleted) yield node.point;
yield* flatten(node.left);
yield* flatten(node.right);
}
void deleteTreeNodes(Node? node) {
if (node == null) return;
_pushDown(node);
deleteTreeNodes(node.left);
deleteTreeNodes(node.right);
}
double _calcDist(Vector2 a, Vector2 b) {
double dist = 0;
for (var dim = 0; dim < _dimensions; dim++) {
dist += math.pow(a[dim] - b[dim], 2);
}
return dist;
}
// checked
double _calcBoxDist(Node? node, Vector2 point) {
if (node == null) return double.infinity;
double minDist = 0;
for (var dim = 0; dim < _dimensions; dim++) {
if (point[dim] < node.aabb.min[dim]) {
minDist += math.pow(point[dim] - node.aabb.min[dim], 2);
}
if (point[dim] > node.aabb.max[dim]) {
minDist += math.pow(point[dim] - node.aabb.max[dim], 2);
}
}
return minDist;
}
void _search(Node? node, int maxNodes, Vector2 point, BinaryHeap<Result> heap,
double maxDist) {
if (node == null || node.treeDeleted) return;
double curDist = _calcBoxDist(node, point);
double maxDistSqr = maxDist * maxDist;
if (curDist > maxDistSqr) return;
if (node.needPushDownToLeft || node.needPushDownToRight) {
_pushDown(node);
}
if (!node.deleted) {
double dist = _calcDist(point, node.point);
if (dist <= maxDistSqr &&
(heap.size() < maxNodes || dist < heap.peek().distance)) {
if (heap.size() >= maxNodes) heap.pop();
heap.push(Result(node, dist));
}
}
double distLeftNode = _calcBoxDist(node.left, point);
double distRightNode = _calcBoxDist(node.right, point);
if (heap.size() < maxNodes ||
distLeftNode < heap.peek().distance &&
distRightNode < heap.peek().distance) {
if (distLeftNode <= distRightNode) {
_search(node.left, maxNodes, point, heap, maxDist);
if (heap.size() < maxNodes || distRightNode < heap.peek().distance) {
_search(node.right, maxNodes, point, heap, maxDist);
}
} else {
_search(node.right, maxNodes, point, heap, maxDist);
if (heap.size() < maxNodes || distLeftNode < heap.peek().distance) {
_search(node.left, maxNodes, point, heap, maxDist);
}
}
} else {
if (distLeftNode < heap.peek().distance) {
_search(node.left, maxNodes, point, heap, maxDist);
}
if (distRightNode < heap.peek().distance) {
_search(node.right, maxNodes, point, heap, maxDist);
}
}
}
/// Find the [maxNodes] of nearest Nodes.
/// Distance is calculated via Metric function.
/// Max distance can be set with [maxDistance] param
Iterable<Vector2> nearest(Vector2 point,
{int maxNodes = 1, double maxDistance = double.infinity}) sync* {
var heap = BinaryHeap<Result>((e) => -e.distance);
_search(_root, maxNodes, point, heap, maxDistance);
var found = math.min(maxNodes, heap.content.length);
for (var i = 0; i < found; i++) {
yield heap.content[i].node.point;
}
}
int get length => _root?.length ?? 0;
int get height => _root?.height ?? 0;
}
class Result {
final Node node;
final double distance;
const Result(this.node, this.distance);
}
class Node {
Vector2 point;
int dimension = 0;
Node? parent;
Node? left;
Node? right;
int treeSize = 0;
int invalidNum = 0;
int downDeletedNum = 0;
bool deleted = false;
bool treeDeleted = false;
bool needPushDownToLeft = false;
bool needPushDownToRight = false;
bool treeDownsampleDeleted = false;
bool pointDownsampleDeleted = false;
AABB aabb = AABB();
Node(this.point);
int get length {
return 1 +
(left == null ? 0 : left!.length) +
(right == null ? 0 : right!.length);
}
int get height {
return 1 +
math.max(
left == null ? 0 : left!.height,
right == null ? 0 : right!.height,
);
}
int get depth {
return 1 + (parent == null ? 0 : parent!.depth);
}
}

Javascript - getElementID from scratch using BFS?

I'm trying to learn javascript, and spent tonight writing a getElementByID() function using Breadth-First Search. In short: I'm lost.
Fiddle: http://jsfiddle.net/timdown/a2Fm6/
Code:
var nodes = [];
function getElementById(node, id) {
alert(nodes.length);
if (node.childNodes[i].id == id) {
return node.childNodes[i];
} else if (node.childNodes[i].length > 0) {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
nodes.push(node.childNodes[i]);
}
}
if (nodes.length > 0) {
getElementById(nodes[0], id);
}
}
var el = getElementById(document.body, 'id');
Any help?
You're missing a for loop in the top half of your code. Where is i defined?
Here's how I'd write it:
function getElementById(node, id) {
//An array of all the nodes at the same depth
var nodes = [node];
//While the array is not empty
while(nodes.length) {
var newNodes = [];
for(var i = 0; i < nodes.length; i++) {
var children = nodes[i].childNodes;
for(var j = 0; j < children.length; j++) {
var child = children[j];
if(child.id == id) {
return child
}
newNodes.push(child);
}
}
//Replace nodes with an array of the nodes the next level down
nodes = newNodes
}
}

Resources