public IEnumerable <Element> Values(float x1, float y1, float x2, float y2) { RegionLock.EnterReadLock(); try { // get the starting row,col and ending row,col GetRegion(x1, y1, out int r1, out int c1, validate: false); GetRegion(x2, y2, out int r2, out int c2, validate: false); // assuming we start to 0,0 in the upper left and corner and increase right and down // ensure r1,c1 if the upper left and corner if (r2 < r1) { // swap var tmp = r1; r1 = r2; r2 = tmp; } if (c2 < c1) { var tmp = c1; c1 = c2; c2 = tmp; } // expand the region r1 -= 1; c1 -= 1; r2 += 1; c2 += 1; // hold the lock for the duration of this call for (int r = (r1 >= 0 ? r1 : 0); r <= r2 && r < Regions.Length; r++) { for (int c = (c1 >= 0 ? c1 : 0); c <= c2 && c < Regions[r].Length; c++) { if (Regions[r][c].Count == 0) { continue; } foreach (var elem in Regions[r][c].Values) { yield return(elem); } } } // always return the oversized items foreach (var elem in Oversized.Values) { yield return(elem); } } finally { RegionLock.ExitReadLock(); } }
public Region GetRegion(Element elem) { if (elem == null) { throw new Exception("Invalid element to get region"); } RegionLock.EnterReadLock(); try { if (IsOversized(elem)) { return(new Region(-1, -1)); } GetRegion(elem.X, elem.Y, out int row, out int column); return(new Region(row, column)); } finally { RegionLock.ExitReadLock(); } }