public List <Node <T> > FindNodes(AABB queryAABB, bool strictMode = false, List <Node <T> > into = null, AdditionalCheckDelegate additionalCheck = null) { var res = into != null ? into : new List <Node <T> >(); if (_root == null) { return(res); } var stack = new Stack <Node <T> >(); stack.Push(_root); //var cnt = 0; while (stack.Count > 0) { var node = stack.Pop(); //cnt++; if (!queryAABB.overlaps(node.aabb)) { continue; } if (node.isLeaf() && (!strictMode || (queryAABB.contains(node.aabb)))) { if (additionalCheck == null) { res.Add(node); } else { var hitBehaviour = additionalCheck(node); if (hitBehaviour == HitBehaviour.INCLUDE || hitBehaviour == HitBehaviour.INCLUDE_AND_STOP) { res.Add(node); } if (hitBehaviour == HitBehaviour.STOP || hitBehaviour == HitBehaviour.INCLUDE_AND_STOP) { break; } } } else { if (node.left != null) { stack.Push(node.left); } if (node.right != null) { stack.Push(node.right); } } } //trace("examined: " + cnt); return(res); }
public List <T> FindValuesAt(AABB targetAABB, bool strictMode = false, AdditionalCheckDelegate callback = null) { var result = new List <T>(); TryFindValuesAt(targetAABB, out result, strictMode, callback); return(result); }
public bool TryFindValuesAt(AABB targetAABB, out List <T> results, bool strictMode = false, AdditionalCheckDelegate callback = null) { var result = Query(targetAABB, strictMode); results = result; if (result.Count == 0) { return(false); } return(true); }
/** * Queries the tree for objects crossing the specified ray. * * Notes: * - the intersecting objects will be returned in no particular order (closest ones to the start point may appear later in the list!). * - the additionalCheck will also be called if an object fully contains the ray's start and end point. * * TODO: see how this can be optimized and return results in order * * @param into Hit objects will be appended to this (based on additionalCheck return value). * @param additionalCheck A function called for every object hit (function additionalCheck(data:T, id:Int):HitBehaviour). * * @return A list of all the objects found (or `into` if it was specified). */ public List <T> RayCast(float fromX, float fromY, float toX, float toY, List <T> into, AdditionalCheckDelegate additionalCheck) { var res = into != null ? into : new List <T>(); if (_root == null) { return(res); } var queryAABBResults = new List <Node <T> >(); float tmp; var rayAABB = new AABB(fromX, fromY, toX - fromX, toY - fromY); if (rayAABB.minX > rayAABB.maxX) { tmp = rayAABB.maxX; rayAABB.maxX = rayAABB.minX; rayAABB.minX = tmp; } if (rayAABB.minY > rayAABB.maxY) { tmp = rayAABB.maxY; rayAABB.maxY = rayAABB.minY; rayAABB.minY = tmp; } Query(rayAABB, false, null, (node) => { var aabb = node.aabb; var fromPointAABB = new AABB(fromX, fromY); var hit = false; for (int i = 0; i < 4; i++) { // test for intersection with node's aabb edges switch (i) { case 0: // top edge hit = SegmentIntersect(fromX, fromY, toX, toY, aabb.minX, aabb.minY, aabb.maxX, aabb.minY); break; case 1: // left edge hit = SegmentIntersect(fromX, fromY, toX, toY, aabb.minX, aabb.minY, aabb.minX, aabb.maxY); break; case 2: // bottom edge hit = SegmentIntersect(fromX, fromY, toX, toY, aabb.minX, aabb.maxY, aabb.maxX, aabb.maxY); break; case 3: // right edge hit = SegmentIntersect(fromX, fromY, toX, toY, aabb.maxX, aabb.minY, aabb.maxX, aabb.maxY); break; default: break; } if (hit) { break; } } // add intersected node id to array if (hit || (aabb.contains(fromPointAABB))) { queryAABBResults.Add(node); } return(HitBehaviour.SKIP); // don't bother adding to results }); foreach (var node in queryAABBResults) { if (additionalCheck != null) { var hitBehaviour = additionalCheck(node); if (hitBehaviour == HitBehaviour.INCLUDE || hitBehaviour == HitBehaviour.INCLUDE_AND_STOP) { res.Add(node.data); } if (hitBehaviour == HitBehaviour.STOP || hitBehaviour == HitBehaviour.INCLUDE_AND_STOP) { break; } } else { res.Add(node.data); } } return(res); }
/** * Queries the tree for objects overlapping the specified point. * * @param into Hit objects will be appended to this (based on additionalCheck return value). * @param additionalCheck A function called for every object hit (function additionalCheck(data:*, id:int):HitBehaviour). * * @return A list of all the objects found (or `into` if it was specified). */ public List <T> QueryPoint(float x, float y, List <T> into, AdditionalCheckDelegate additionalCheck) { return(Query(new AABB(x, y), false, into, additionalCheck)); }
public bool TryFindValuesAt(FloatWithSizeMath.FloatWithSize[] targetAABB, out List <T> results, bool strictMode = false, AdditionalCheckDelegate callback = null) { var result = Query(targetAABB[0].MinVal, targetAABB[1].MinVal, targetAABB[0].Size, targetAABB[1].Size, strictMode); results = result; if (result.Count == 0) { return(false); } return(true); }