Skip to main content
removed the `outp` name.
Source Link
Jesse C. Slicer
  • 14.6k
  • 1
  • 40
  • 54
internal sealed class Root<T>
{
    private readonly Leaf<T> rootLeaf = new Leaf<T>();

    // dictionary contains a reference to each item, and the leaf it is assigned to (its parent)
    private readonly IDictionary<T, Leaf<T>> allItems = new Dictionary<T, Leaf<T>>();

    /// <summary>
    /// Gets GetAllChildren.
    /// </summary>
    public IList<T> GetAllChildren
    {
        get
        {
            return this.rootLeaf.GetAllChildren;
        }
    }

    public void Add(T o)
    {
        var addedTo = this.rootLeaf.Add(o);

        this.allItems.Add(o, addedTo); // Add object reference to AllItems dictionary
    }

    public void Update()
    {
        foreach (var i in from i in this.allItems from b in this.GetNeighbors(i.Key) select i)
        {
            // Would do collision checks here
        }
    }

    private IEnumerable<T> GetNeighbors(T obj)
    {
        return this.allItems[obj].GetAllChildren.Where(o => ReferenceEquals(obj, o));
    }
}

internal class Leaf<T>
{
    private const int MaxChildCount = 1;

    private static readonly Random rand = new Random();

    private readonly IList<T> children = new List<T>();

    private List<Leaf<T>> childLeaves;

    private bool hasLeaves; // Should we use the leaves?

    private bool leavesGenerated; // Have the leaves been created? (Low Level, do not touch)

    /// <summary>
    /// Returns children of this leaf, and all of its subleaves
    /// </summary>
    public IList<T> GetAllChildren
    {
        get
        {
            var outpallChildren = this.children.ToList();

            if (this.hasLeaves)
            {
                this.childLeaves.ToList().ForEach(l => outpallChildren.AddRange(l.GetAllChildren));
            }

            return outp;allChildren;
        }
    }

    /// <summary>
    /// Get count of all children in this leaf, and its subleaves
    /// </summary>
    public int GetChildCount
    {
        get
        {
            var outpallChildrenCount = this.children.Count;

            if (this.hasLeaves)
            {
                outpallChildrenCount += this.childLeaves.Sum(l => l.GetChildCount);
            }

            return outp;allChildrenCount;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="o">The object to be added</param>
    /// <returns>The leaf the object was added to</returns>
    public Leaf<T> Add(T o)
    {
        if (this.children.Count < MaxChildCount)
        {
            this.children.Add(o);
            return this;
        }

        // Pick random subleaf, I know this isn't correct for a quadtree, but it will simplify this explanation code
        if (!this.hasLeaves)
        {
            this.CreateLeaves();
        }

        return this.childLeaves[rand.Next(0, 3)].Add(o);
    }

    protected void CreateLeaves()
    {
        if (!this.leavesGenerated)
        {
            // create each of the four leaves
            this.childLeaves = new List<Leaf<T>> { new Leaf<T>(), new Leaf<T>(), new Leaf<T>(), new Leaf<T>() };

            this.leavesGenerated = true;
        }

        this.hasLeaves = true;
    }

    protected void RemoveLeaves()
    {
        this.hasLeaves = false;
    }
}
internal sealed class Root<T>
{
    private readonly Leaf<T> rootLeaf = new Leaf<T>();

    // dictionary contains a reference to each item, and the leaf it is assigned to (its parent)
    private readonly IDictionary<T, Leaf<T>> allItems = new Dictionary<T, Leaf<T>>();

    /// <summary>
    /// Gets GetAllChildren.
    /// </summary>
    public IList<T> GetAllChildren
    {
        get
        {
            return this.rootLeaf.GetAllChildren;
        }
    }

    public void Add(T o)
    {
        var addedTo = this.rootLeaf.Add(o);

        this.allItems.Add(o, addedTo); // Add object reference to AllItems dictionary
    }

    public void Update()
    {
        foreach (var i in from i in this.allItems from b in this.GetNeighbors(i.Key) select i)
        {
            // Would do collision checks here
        }
    }

    private IEnumerable<T> GetNeighbors(T obj)
    {
        return this.allItems[obj].GetAllChildren.Where(o => ReferenceEquals(obj, o));
    }
}

internal class Leaf<T>
{
    private const int MaxChildCount = 1;

    private static readonly Random rand = new Random();

    private readonly IList<T> children = new List<T>();

    private List<Leaf<T>> childLeaves;

    private bool hasLeaves; // Should we use the leaves?

    private bool leavesGenerated; // Have the leaves been created? (Low Level, do not touch)

    /// <summary>
    /// Returns children of this leaf, and all of its subleaves
    /// </summary>
    public IList<T> GetAllChildren
    {
        get
        {
            var outp = this.children.ToList();

            if (this.hasLeaves)
            {
                this.childLeaves.ToList().ForEach(l => outp.AddRange(l.GetAllChildren));
            }

            return outp;
        }
    }

    /// <summary>
    /// Get count of all children in this leaf, and its subleaves
    /// </summary>
    public int GetChildCount
    {
        get
        {
            var outp = this.children.Count;

            if (this.hasLeaves)
            {
                outp += this.childLeaves.Sum(l => l.GetChildCount);
            }

            return outp;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="o">The object to be added</param>
    /// <returns>The leaf the object was added to</returns>
    public Leaf<T> Add(T o)
    {
        if (this.children.Count < MaxChildCount)
        {
            this.children.Add(o);
            return this;
        }

        // Pick random subleaf, I know this isn't correct for a quadtree, but it will simplify this explanation code
        if (!this.hasLeaves)
        {
            this.CreateLeaves();
        }

        return this.childLeaves[rand.Next(0, 3)].Add(o);
    }

    protected void CreateLeaves()
    {
        if (!this.leavesGenerated)
        {
            // create each of the four leaves
            this.childLeaves = new List<Leaf<T>> { new Leaf<T>(), new Leaf<T>(), new Leaf<T>(), new Leaf<T>() };

            this.leavesGenerated = true;
        }

        this.hasLeaves = true;
    }

    protected void RemoveLeaves()
    {
        this.hasLeaves = false;
    }
}
internal sealed class Root<T>
{
    private readonly Leaf<T> rootLeaf = new Leaf<T>();

    // dictionary contains a reference to each item, and the leaf it is assigned to (its parent)
    private readonly IDictionary<T, Leaf<T>> allItems = new Dictionary<T, Leaf<T>>();

    /// <summary>
    /// Gets GetAllChildren.
    /// </summary>
    public IList<T> GetAllChildren
    {
        get
        {
            return this.rootLeaf.GetAllChildren;
        }
    }

    public void Add(T o)
    {
        var addedTo = this.rootLeaf.Add(o);

        this.allItems.Add(o, addedTo); // Add object reference to AllItems dictionary
    }

    public void Update()
    {
        foreach (var i in from i in this.allItems from b in this.GetNeighbors(i.Key) select i)
        {
            // Would do collision checks here
        }
    }

    private IEnumerable<T> GetNeighbors(T obj)
    {
        return this.allItems[obj].GetAllChildren.Where(o => ReferenceEquals(obj, o));
    }
}

internal class Leaf<T>
{
    private const int MaxChildCount = 1;

    private static readonly Random rand = new Random();

    private readonly IList<T> children = new List<T>();

    private List<Leaf<T>> childLeaves;

    private bool hasLeaves; // Should we use the leaves?

    private bool leavesGenerated; // Have the leaves been created? (Low Level, do not touch)

    /// <summary>
    /// Returns children of this leaf, and all of its subleaves
    /// </summary>
    public IList<T> GetAllChildren
    {
        get
        {
            var allChildren = this.children.ToList();

            if (this.hasLeaves)
            {
                this.childLeaves.ToList().ForEach(l => allChildren.AddRange(l.GetAllChildren));
            }

            return allChildren;
        }
    }

    /// <summary>
    /// Get count of all children in this leaf, and its subleaves
    /// </summary>
    public int GetChildCount
    {
        get
        {
            var allChildrenCount = this.children.Count;

            if (this.hasLeaves)
            {
                allChildrenCount += this.childLeaves.Sum(l => l.GetChildCount);
            }

            return allChildrenCount;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="o">The object to be added</param>
    /// <returns>The leaf the object was added to</returns>
    public Leaf<T> Add(T o)
    {
        if (this.children.Count < MaxChildCount)
        {
            this.children.Add(o);
            return this;
        }

        // Pick random subleaf, I know this isn't correct for a quadtree, but it will simplify this explanation code
        if (!this.hasLeaves)
        {
            this.CreateLeaves();
        }

        return this.childLeaves[rand.Next(0, 3)].Add(o);
    }

    protected void CreateLeaves()
    {
        if (!this.leavesGenerated)
        {
            // create each of the four leaves
            this.childLeaves = new List<Leaf<T>> { new Leaf<T>(), new Leaf<T>(), new Leaf<T>(), new Leaf<T>() };

            this.leavesGenerated = true;
        }

        this.hasLeaves = true;
    }

    protected void RemoveLeaves()
    {
        this.hasLeaves = false;
    }
}
Source Link
Jesse C. Slicer
  • 14.6k
  • 1
  • 40
  • 54

All right, I've done a bit of work here (a good most of it stylistic, to be sure). Do note I replaced object with a generic implementation to help avoid boxing of value types. It does also employ LINQ in a couple instances to remove some complexity. When I run it and generate 1,000,000 integer leaves, I find that the bulk of the time is taken in the class constructors and the methods themselves are close enough to 0 time to be considered 0. Hope this helps:

internal sealed class Root<T>
{
    private readonly Leaf<T> rootLeaf = new Leaf<T>();

    // dictionary contains a reference to each item, and the leaf it is assigned to (its parent)
    private readonly IDictionary<T, Leaf<T>> allItems = new Dictionary<T, Leaf<T>>();

    /// <summary>
    /// Gets GetAllChildren.
    /// </summary>
    public IList<T> GetAllChildren
    {
        get
        {
            return this.rootLeaf.GetAllChildren;
        }
    }

    public void Add(T o)
    {
        var addedTo = this.rootLeaf.Add(o);

        this.allItems.Add(o, addedTo); // Add object reference to AllItems dictionary
    }

    public void Update()
    {
        foreach (var i in from i in this.allItems from b in this.GetNeighbors(i.Key) select i)
        {
            // Would do collision checks here
        }
    }

    private IEnumerable<T> GetNeighbors(T obj)
    {
        return this.allItems[obj].GetAllChildren.Where(o => ReferenceEquals(obj, o));
    }
}

internal class Leaf<T>
{
    private const int MaxChildCount = 1;

    private static readonly Random rand = new Random();

    private readonly IList<T> children = new List<T>();

    private List<Leaf<T>> childLeaves;

    private bool hasLeaves; // Should we use the leaves?

    private bool leavesGenerated; // Have the leaves been created? (Low Level, do not touch)

    /// <summary>
    /// Returns children of this leaf, and all of its subleaves
    /// </summary>
    public IList<T> GetAllChildren
    {
        get
        {
            var outp = this.children.ToList();

            if (this.hasLeaves)
            {
                this.childLeaves.ToList().ForEach(l => outp.AddRange(l.GetAllChildren));
            }

            return outp;
        }
    }

    /// <summary>
    /// Get count of all children in this leaf, and its subleaves
    /// </summary>
    public int GetChildCount
    {
        get
        {
            var outp = this.children.Count;

            if (this.hasLeaves)
            {
                outp += this.childLeaves.Sum(l => l.GetChildCount);
            }

            return outp;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="o">The object to be added</param>
    /// <returns>The leaf the object was added to</returns>
    public Leaf<T> Add(T o)
    {
        if (this.children.Count < MaxChildCount)
        {
            this.children.Add(o);
            return this;
        }

        // Pick random subleaf, I know this isn't correct for a quadtree, but it will simplify this explanation code
        if (!this.hasLeaves)
        {
            this.CreateLeaves();
        }

        return this.childLeaves[rand.Next(0, 3)].Add(o);
    }

    protected void CreateLeaves()
    {
        if (!this.leavesGenerated)
        {
            // create each of the four leaves
            this.childLeaves = new List<Leaf<T>> { new Leaf<T>(), new Leaf<T>(), new Leaf<T>(), new Leaf<T>() };

            this.leavesGenerated = true;
        }

        this.hasLeaves = true;
    }

    protected void RemoveLeaves()
    {
        this.hasLeaves = false;
    }
}