/// <summary> /// Perform a line query on this index. This will return all entries in the index that are intersecting with the /// specified query line. /// </summary> /// <param name="start">The start point.</param> /// <param name="end">The end point.</param> /// <param name="t">The fraction along the line to consider.</param> /// <param name="results">The list to put the results into.</param> /// <returns></returns> public void Find(TPoint start, TPoint end, float t, ISet <T> results) { foreach (var cell in ComputeCells(IntersectionExtensions.BoundsFor(start, end, t))) { if (_cells.ContainsKey(cell.Item1)) { // Convert the query to the tree's local coordinate space. // ReSharper disable RedundantCast Necessary for FarCollections. var relativeStart = (Vector2)(start + cell.Item2); var relativeEnd = (Vector2)(end + cell.Item2); // ReSharper restore RedundantCast // And do the query. _cells[cell.Item1].Find(relativeStart, relativeEnd, t, results); } } }
/// <summary> /// Perform a circular query on this index. This will return all entries in the index that are in the specified range /// of the specified point, using the euclidean distance function (i.e. <c>sqrt(x*x+y*y)</c>). /// </summary> /// <param name="center">The query point near which to get entries.</param> /// <param name="radius">The maximum distance an entry may be away from the query point to be returned.</param> /// <param name="results"> </param> /// <remarks> /// This checks for intersections of the query circle and the bounds of the entries in the index. Intersections /// (i.e. bounds not fully contained in the circle) will be returned, too. /// </remarks> public void Find(TPoint center, float radius, ISet <T> results) { // Compute the area bounds for that query to get the involved trees. var queryBounds = IntersectionExtensions.BoundsFor(center, radius); foreach (var cell in ComputeCells(queryBounds)) { // Only if the cell exists. if (_cells.ContainsKey(cell.Item1)) { // Convert the query to the tree's local coordinate space. // ReSharper disable RedundantCast Necessary for FarCollections. var relativePoint = (Vector2)(center + cell.Item2); // ReSharper restore RedundantCast // And do the query. _cells[cell.Item1].Find(relativePoint, radius, results); } } }
/// <summary> /// Perform a line query on this index. This will return all entries in the index that are intersecting with the /// specified query line. /// <para> /// Note that the callback will be passed the fraction along the line that the hit occurred at, and may return /// the new maximum fraction up to which the search will run. If the returned fraction is exactly zero the search /// will be stopped. If the returned fraction is negative the hit will be ignored, that is the max fraction will /// not change. /// </para> /// </summary> /// <param name="start">The start of the line.</param> /// <param name="end">The end of the line.</param> /// <param name="t">The fraction along the line to consider.</param> /// <param name="callback">The method to call for each found hit.</param> /// <returns></returns> public bool Find(TPoint start, TPoint end, float t, LineQueryCallback <T> callback) { // HashSet we might use for filtering duplicate results. We initialize it lazily. HashSet <T> filter = null; foreach (var cell in ComputeCells(IntersectionExtensions.BoundsFor(start, end, t))) { if (_cells.ContainsKey(cell.Item1)) { // Convert the query to the tree's local coordinate space. // ReSharper disable RedundantCast Necessary for FarCollections. var relativeStart = (Vector2)(start + cell.Item2); var relativeEnd = (Vector2)(end + cell.Item2); // ReSharper restore RedundantCast // And do the query. if (!_cells[cell.Item1].Find( relativeStart, relativeEnd, t, (value, fraction) => { if (!Filter(value, ref filter)) { return(-1f); } return(t = callback(value, fraction)); })) { return(false); } } } return(true); }