do not return duplicate values from spatial hash

pull/17/head
cosmonaut 2022-03-19 10:48:23 -07:00
parent 4fda9a2ce5
commit 8aa64fc664
1 changed files with 39 additions and 6 deletions

View File

@ -19,6 +19,7 @@ namespace MoonWorks.Collision
public int MinY { get; private set; } = 0; public int MinY { get; private set; } = 0;
public int MaxY { get; private set; } = 0; public int MaxY { get; private set; } = 0;
private Queue<HashSet<T>> hashSetPool = new Queue<HashSet<T>>();
public SpatialHash2D(int cellSize) public SpatialHash2D(int cellSize)
{ {
@ -68,6 +69,8 @@ namespace MoonWorks.Collision
/// </summary> /// </summary>
public IEnumerable<(T, IHasAABB2D, Transform2D)> Retrieve(T id, IHasAABB2D shape, Transform2D transform2D) public IEnumerable<(T, IHasAABB2D, Transform2D)> Retrieve(T id, IHasAABB2D shape, Transform2D transform2D)
{ {
var returned = AcquireHashSet();
var box = shape.TransformedAABB(transform2D); var box = shape.TransformedAABB(transform2D);
var (minX, minY) = Hash(box.Min); var (minX, minY) = Hash(box.Min);
var (maxX, maxY) = Hash(box.Max); var (maxX, maxY) = Hash(box.Max);
@ -86,15 +89,21 @@ namespace MoonWorks.Collision
{ {
foreach (var t in hashDictionary[key]) foreach (var t in hashDictionary[key])
{ {
var (otherShape, otherTransform) = IDLookup[t]; if (!returned.Contains(t))
if (!id.Equals(t) && AABB2D.TestOverlap(box, otherShape.TransformedAABB(otherTransform)))
{ {
yield return (t, otherShape, otherTransform); var (otherShape, otherTransform) = IDLookup[t];
if (!id.Equals(t) && AABB2D.TestOverlap(box, otherShape.TransformedAABB(otherTransform)))
{
returned.Add(t);
yield return (t, otherShape, otherTransform);
}
} }
} }
} }
} }
} }
FreeHashSet(returned);
} }
@ -105,6 +114,8 @@ namespace MoonWorks.Collision
/// <returns></returns> /// <returns></returns>
public IEnumerable<(T, IHasAABB2D, Transform2D)> Retrieve(AABB2D aabb) public IEnumerable<(T, IHasAABB2D, Transform2D)> Retrieve(AABB2D aabb)
{ {
var returned = AcquireHashSet();
var (minX, minY) = Hash(aabb.Min); var (minX, minY) = Hash(aabb.Min);
var (maxX, maxY) = Hash(aabb.Max); var (maxX, maxY) = Hash(aabb.Max);
@ -122,15 +133,20 @@ namespace MoonWorks.Collision
{ {
foreach (var t in hashDictionary[key]) foreach (var t in hashDictionary[key])
{ {
var (otherShape, otherTransform) = IDLookup[t]; if (!returned.Contains(t))
if (AABB2D.TestOverlap(aabb, otherShape.TransformedAABB(otherTransform)))
{ {
yield return (t, otherShape, otherTransform); var (otherShape, otherTransform) = IDLookup[t];
if (AABB2D.TestOverlap(aabb, otherShape.TransformedAABB(otherTransform)))
{
yield return (t, otherShape, otherTransform);
}
} }
} }
} }
} }
} }
FreeHashSet(returned);
} }
/// <summary> /// <summary>
@ -150,5 +166,22 @@ namespace MoonWorks.Collision
{ {
return ((long) left << 32) | ((uint) right); return ((long) left << 32) | ((uint) right);
} }
private HashSet<T> AcquireHashSet()
{
if (hashSetPool.Count == 0)
{
hashSetPool.Enqueue(new HashSet<T>());
}
var hashSet = hashSetPool.Dequeue();
hashSet.Clear();
return hashSet;
}
private void FreeHashSet(HashSet<T> hashSet)
{
hashSetPool.Enqueue(hashSet);
}
} }
} }