Speed up SpatiallyPartitioned.InBox for searches in a single partition bin.
If a search in a spatial partition is taking place entirely within a single bin, the cost of tracking possible duplicate items with a set can be avoided for a small speedup.
This commit is contained in:
@@ -86,7 +86,11 @@ namespace OpenRA.Primitives
|
||||
var top = (box.Top / binSize).Clamp(0, rows - 1);
|
||||
var bottom = (box.Bottom / binSize).Clamp(0, rows - 1);
|
||||
|
||||
var items = new HashSet<T>();
|
||||
// We want to return any items intersecting the box.
|
||||
// If the box covers multiple bins, we must handle items that are contained in multiple bins and avoid
|
||||
// returning them more than once. We shall use a set to track these.
|
||||
// PERF: If we are only looking inside one bin, we can avoid the cost of performing this tracking.
|
||||
var items = top == bottom && left == right ? null : new HashSet<T>();
|
||||
for (var row = top; row <= bottom; row++)
|
||||
for (var col = left; col <= right; col++)
|
||||
{
|
||||
@@ -96,10 +100,12 @@ namespace OpenRA.Primitives
|
||||
var item = kvp.Key;
|
||||
var bounds = kvp.Value;
|
||||
|
||||
// Return items that intersect the box. We also want to avoid returning the same item many times.
|
||||
// If the item is contained wholly within this bin, we're good as we know it won't show up in any others.
|
||||
// Otherwise it may appear in another bin. We use a set of seen items to avoid yielding it again.
|
||||
if (bounds.IntersectsWith(box) && (binBounds.Contains(bounds) || items.Add(item)))
|
||||
// If the item is in the bin, we must check it intersects the box before returning it.
|
||||
// We shall track it in the set of items seen so far to avoid returning it again if it appears
|
||||
// in another bin.
|
||||
// PERF: If the item is wholly contained within the bin, we can avoid the cost of tracking it.
|
||||
if (bounds.IntersectsWith(box) &&
|
||||
(items == null || binBounds.Contains(bounds) || items.Add(item)))
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user