/// <summary> /// Query the index for nodes with a rectangle. /// Points that lie exactly on the edge of the rectangle are /// considered to be within the rectangle and will be returned /// </summary> /// <param name="x1">min x</param> /// <param name="y1">min y</param> /// <param name="x2">max x</param> /// <param name="y2">max y</param> public List <Point <T> > Query(double x1, double y1, double x2, double y2) { List <Point <T> > hitPoints = new List <Point <T> >(); Stack <SearchState> stack = new Stack <SearchState>(); stack.Push(new SearchState(0, points.Count - 1, SearchAxis.XAxis)); double x; double y; while (stack.Count > 0) { SearchState state = stack.Pop(); if (state.End - state.Start <= nodeSize) { for (var i = state.Start; i <= state.End; i++) { x = points[i].X; y = points[i].Y; if (x >= x1 && x <= x2 && y >= y1 && y <= y2) { hitPoints.Add(points[i]); } } continue; } int m = (state.Start + state.End) / 2; x = points[m].X; y = points[m].Y; if (x >= x1 && x <= x2 && y >= y1 && y <= y2) { hitPoints.Add(points[m]); } SearchAxis nextAxis = (state.Axis == SearchAxis.XAxis) ? SearchAxis.YAxis : SearchAxis.XAxis; if ((state.Axis == SearchAxis.XAxis) ? x1 <= x : y1 <= y) { stack.Push(new SearchState(state.Start, m - 1, nextAxis)); } if ((state.Axis == SearchAxis.XAxis) ? x2 >= x : y2 >= y) { stack.Push(new SearchState(m + 1, state.End, nextAxis)); } } return(hitPoints); }
/// <summary> /// Query the index for nodes with a circle. /// Points that lie exactly on the edge of the circle are /// considered to be within the circle and will be returned /// </summary> /// <param name="x">center X of the circle</param> /// <param name="y">center Y of the circle</param> /// <param name="radius">radius of the circle</param> public List <Point <T> > Query(double x, double y, double radius) { List <Point <T> > hitPoints = new List <Point <T> >(); Stack <SearchState> stack = new Stack <SearchState>(); stack.Push(new SearchState(0, points.Count - 1, SearchAxis.XAxis)); double r2 = radius * radius; while (stack.Count > 0) { SearchState state = stack.Pop(); if ((state.End - state.Start) <= nodeSize) { for (var i = state.Start; i <= state.End; i++) { if (SquareDistance(points[i].X, points[i].Y, x, y) <= r2) { hitPoints.Add(points[i]); } } continue; } int m = (state.Start + state.End) / 2; double px = points[m].X; double py = points[m].Y; if (SquareDistance(px, py, x, y) <= r2) { hitPoints.Add(points[m]); } SearchAxis nextAxis = (state.Axis == SearchAxis.XAxis) ? SearchAxis.YAxis : SearchAxis.XAxis; if ((state.Axis == SearchAxis.XAxis) ? x - radius <= px : y - radius <= py) { stack.Push(new SearchState(state.Start, m - 1, nextAxis)); } if ((state.Axis == SearchAxis.XAxis) ? x + radius >= px : y + radius >= py) { stack.Push(new SearchState(m + 1, state.End, nextAxis)); } } return(hitPoints); }
public SearchState(int start, int end, SearchAxis axis) { Axis = axis; Start = start; End = end; }