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);
@ -85,10 +88,13 @@ namespace MoonWorks.Collision
if (hashDictionary.ContainsKey(key)) if (hashDictionary.ContainsKey(key))
{ {
foreach (var t in hashDictionary[key]) foreach (var t in hashDictionary[key])
{
if (!returned.Contains(t))
{ {
var (otherShape, otherTransform) = IDLookup[t]; var (otherShape, otherTransform) = IDLookup[t];
if (!id.Equals(t) && AABB2D.TestOverlap(box, otherShape.TransformedAABB(otherTransform))) if (!id.Equals(t) && AABB2D.TestOverlap(box, otherShape.TransformedAABB(otherTransform)))
{ {
returned.Add(t);
yield return (t, otherShape, otherTransform); yield return (t, otherShape, otherTransform);
} }
} }
@ -97,6 +103,9 @@ namespace MoonWorks.Collision
} }
} }
FreeHashSet(returned);
}
/// <summary> /// <summary>
/// Retrieves objects based on a pre-transformed AABB. /// Retrieves objects based on a pre-transformed AABB.
@ -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);
@ -121,6 +132,8 @@ namespace MoonWorks.Collision
if (hashDictionary.ContainsKey(key)) if (hashDictionary.ContainsKey(key))
{ {
foreach (var t in hashDictionary[key]) foreach (var t in hashDictionary[key])
{
if (!returned.Contains(t))
{ {
var (otherShape, otherTransform) = IDLookup[t]; var (otherShape, otherTransform) = IDLookup[t];
if (AABB2D.TestOverlap(aabb, otherShape.TransformedAABB(otherTransform))) if (AABB2D.TestOverlap(aabb, otherShape.TransformedAABB(otherTransform)))
@ -133,6 +146,9 @@ namespace MoonWorks.Collision
} }
} }
FreeHashSet(returned);
}
/// <summary> /// <summary>
/// Removes everything that has been inserted into the SpatialHash. /// Removes everything that has been inserted into the SpatialHash.
/// </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);
}
} }
} }