mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-03-19 16:31:21 +00:00
116 lines
3.9 KiB
C#
116 lines
3.9 KiB
C#
|
using Microsoft.Xna.Framework;
|
|||
|
|
|||
|
namespace FSO.Common.Model
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// A k-d Tree for looking up rectangle intersections
|
|||
|
/// TODO: balancing? could make performance gains more stable at the cost of some of the worst case.
|
|||
|
/// </summary>
|
|||
|
public class IntersectRectTree
|
|||
|
{
|
|||
|
public IntersectRectNode Root;
|
|||
|
|
|||
|
public void Add(Rectangle rect)
|
|||
|
{
|
|||
|
if (Root == null)
|
|||
|
{
|
|||
|
Root = new IntersectRectNode
|
|||
|
{
|
|||
|
Dimension = IntersectRectDimension.Left,
|
|||
|
Rect = rect
|
|||
|
};
|
|||
|
} else
|
|||
|
{
|
|||
|
Root.AddAsChild(rect);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public bool SearchForIntersect(Rectangle rect)
|
|||
|
{
|
|||
|
if (Root == null) return false;
|
|||
|
else
|
|||
|
{
|
|||
|
return Root.SearchForIntersect(rect);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class IntersectRectNode
|
|||
|
{
|
|||
|
public IntersectRectNode LeftChild;
|
|||
|
public IntersectRectNode RightChild;
|
|||
|
public IntersectRectDimension Dimension;
|
|||
|
public Rectangle Rect;
|
|||
|
|
|||
|
public void AddAsChild(Rectangle rect)
|
|||
|
{
|
|||
|
bool rightSide = false;
|
|||
|
switch (Dimension)
|
|||
|
{
|
|||
|
case IntersectRectDimension.Top:
|
|||
|
rightSide = rect.Top > Rect.Top; break;
|
|||
|
case IntersectRectDimension.Left:
|
|||
|
rightSide = rect.Left > Rect.Left; break;
|
|||
|
case IntersectRectDimension.Bottom:
|
|||
|
rightSide = rect.Bottom > Rect.Bottom; break;
|
|||
|
case IntersectRectDimension.Right:
|
|||
|
rightSide = rect.Right > Rect.Right; break;
|
|||
|
}
|
|||
|
if (rightSide)
|
|||
|
{
|
|||
|
if (RightChild != null) RightChild.AddAsChild(rect);
|
|||
|
else
|
|||
|
{
|
|||
|
RightChild = new IntersectRectNode
|
|||
|
{
|
|||
|
Dimension = (IntersectRectDimension)(((int)Dimension + 1) % 4),
|
|||
|
Rect = rect
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (LeftChild != null) LeftChild.AddAsChild(rect);
|
|||
|
else
|
|||
|
{
|
|||
|
LeftChild = new IntersectRectNode
|
|||
|
{
|
|||
|
Dimension = (IntersectRectDimension)(((int)Dimension + 1) % 4),
|
|||
|
Rect = rect
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public bool SearchForIntersect(Rectangle rect)
|
|||
|
{
|
|||
|
if (rect.Intersects(Rect)) return true;
|
|||
|
//search in child nodes.
|
|||
|
int dontSearch = 0;
|
|||
|
switch (Dimension)
|
|||
|
{
|
|||
|
case IntersectRectDimension.Top:
|
|||
|
dontSearch = (rect.Bottom < Rect.Top)?2:0; break; //if true, do not have to search right (where top greater)
|
|||
|
case IntersectRectDimension.Left:
|
|||
|
dontSearch = (rect.Right < Rect.Left)?2:0; break; //if true, do not have to search right (where left greater)
|
|||
|
case IntersectRectDimension.Bottom:
|
|||
|
dontSearch = (rect.Top > Rect.Bottom)?1:0; break; //if true, do not have to search left (where bottom less)
|
|||
|
case IntersectRectDimension.Right:
|
|||
|
dontSearch = (rect.Left > Rect.Right)?1:0; break; //if true, do not have to search left (where right less)
|
|||
|
}
|
|||
|
|
|||
|
//may need to search both :'( won't happen often with our small rectangles over large space though.
|
|||
|
return ((dontSearch != 1 && LeftChild != null && LeftChild.SearchForIntersect(rect))
|
|||
|
|| (dontSearch != 2 && RightChild != null && RightChild.SearchForIntersect(rect)));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public enum IntersectRectDimension : byte
|
|||
|
{
|
|||
|
Top,
|
|||
|
Left,
|
|||
|
Bottom,
|
|||
|
Right
|
|||
|
}
|
|||
|
}
|