All pastes #1209745 Raw Edit

Sithid

public text v1 · immutable
#1209745 ·published 2008-09-23 21:41 UTC
rendered paste body
using System;
using System.Text;
using System.Drawing;
using System.Collections.Generic;

namespace Sithid.QuadTree
{
    public class QuadNode<T> : IQuadObject where T: IQuadObject
    {
        protected const byte _MAX_OBJECTS_ = 4;

        private QuadNode<T> m_Parent;
        private RectangleF m_Bounds;
        private PointF m_Location;

        private List<T> m_BranchItems;
        private List<QuadNode<T>> m_Children;

        private T m_LastObject;

        public QuadNode<T> Parent
        {
            get
            {
                return m_Parent;
            }
            set
            {
                m_Parent = value;
            }
        }

        public RectangleF Bounds
        {
            get
            {
                return m_Bounds;
            }
            set
            {
                m_Bounds = value;
            }
        }

        public PointF Location
        {
            get
            {
                return m_Location;
            }
            set
            {
                m_Location = value;
            }
        }

        public List<T> BranchItems
        {
            get
            {
                return m_BranchItems;
            }
            set
            {
                m_BranchItems = value;
            }
        }

        public List<QuadNode<T>> Children
        {
            get
            {
                return m_Children;
            }
            set
            {
                m_Children = value;
            }
        }

        public bool IsRoot
        {
            get
            {
                return ( m_Parent == this );
            }
        }

        public int TotalObjects
        {
            get
            {
                int count = m_BranchItems.Count;

                if( m_Children != null )
                {
                    for( int i = 0; i < m_Children.Count; ++i )
                    {
                        count += m_Children[i].TotalObjects;
                    }
                }

                return count;
            }
        }

        public QuadNode( RectangleF bounds, QuadNode<T> parent )
        {
            m_Parent = parent == null ? this : parent;
            m_Bounds = bounds;          

            m_BranchItems = new List<T>();
            m_Children = null;
            m_LastObject = default(T);
        }

        public void Add(T val)
        {
            m_LastObject = val;

            QuadNode<T> node = FindParent( val.Bounds, val.Location, m_Parent );

            List<QuadNode<T>> m_Intersects = new List<QuadNode<T>>();

            if( node.Children != null )
            {
                for( int i = 0; i < node.Children.Count; ++i )
                {
                    if( node.Children[i].Bounds.IntersectsWith( val.Bounds ) )
                    {
                        m_Intersects.Add( node.Children[i] ); 
                    }
                }

                if( m_Intersects.Count > 1 )
                {
                    node.BranchItems.Add( val );
                }
                else
                {
                    m_Intersects[0].Add( val );
                }
            }
            else
            {
                if( node.BranchItems != null )
                {
                    if( node.BranchItems.Count < _MAX_OBJECTS_ )
                    {
                        node.BranchItems.Add( val );
                    }
                    else
                    {
                        node.Split();

                        QuadNode<T> recurse = FindParent( val.Bounds, val.Location, node );
                        recurse.Add( val );
                    }
                }
            }
        }

        private QuadNode<T> FindParent( RectangleF bounds, PointF loc, QuadNode<T> recurse )
        {
            if( recurse != null )
            {
                for( int i = 0; recurse.Children != null && i < recurse.Children.Count; ++i )
                {
                    if( recurse.Children[i].Bounds.IntersectsWith( bounds ) )
                    {
                        recurse = FindParent( bounds, loc, recurse.Children[i] );
                    }
                }
            }
            else
            {
                return this;
            }

            return recurse;
        }

        public void Split()
        {
            float x = m_Bounds.Left;
            float y = m_Bounds.Top;

            float halfx = m_Bounds.Width / 2;
            float halfy = m_Bounds.Height / 2;

            m_Children = new List<QuadNode<T>>();

            m_Children.Add( new QuadNode<T>( new RectangleF( x, y, halfx, halfy ), this ) );
            m_Children.Add( new QuadNode<T>( new RectangleF( x + halfx, y, halfx, halfy ), this ) );
            m_Children.Add( new QuadNode<T>( new RectangleF( x, y + halfy, halfx, halfy ), this ) );
            m_Children.Add( new QuadNode<T>( new RectangleF( x + halfx, y + halfy, halfx, halfy ), this ) );

            for( int i = 0; i < m_BranchItems.Count; ++i )
            {
                for( int j = 0; j < m_Children.Count; ++j )
                {
                    if( m_Children[j].Bounds.IntersectsWith( m_BranchItems[i].Bounds ) )
                    {
                        m_Children[j].Add( m_BranchItems[i] );
 
                        m_BranchItems.Remove( m_BranchItems[i] );
                        --i;

                        break;
                    }
                }
            }
        }

        public void Draw( Graphics g, Point mousePos, bool useMouse )
        {
            Brush b = Brushes.Black;
            Pen p = new Pen( Color.Red, 1f );
            PointF p1, p2, p3, p4;

            if( useMouse )
            {
                if( m_Bounds.Contains( mousePos ) )
                {
                    if( m_Children != null )
                    {
                        for( int i = 0; i < m_Children.Count; ++i )
                        {
                            m_Children[i].Draw( g, mousePos, useMouse );
                        }
                    }
                    else
                    {
                        p1 = new PointF( m_Bounds.Left, m_Bounds.Top );
                        p2 = new PointF( m_Bounds.Right, m_Bounds.Top );
                        p3 = new PointF( m_Bounds.Left, m_Bounds.Bottom );
                        p4 = new PointF( m_Bounds.Right, m_Bounds.Bottom );

                        g.DrawLine( p, p1, p2 );
                        g.DrawLine( p, p2, p4 );
                        g.DrawLine( p, p1, p3 );
                        g.DrawLine( p, p3, p4 );

                        for( int i = 0; i < m_BranchItems.Count; ++i )
                        {
                            g.FillRectangle( b, m_BranchItems[i].Bounds );
                        }
                    }
                }

            }
            else
            {
                if( m_Children != null )
                {
                    for( int i = 0; i < m_Children.Count; ++i )
                    {
                        m_Children[i].Draw( g, mousePos, useMouse );
                    }
                }
                else
                {
                    for( int i = 0; i < m_BranchItems.Count; ++i )
                    {
                        g.FillRectangle( b, m_BranchItems[i].Bounds );
                    }

                    p1 = new PointF( m_Bounds.Left, m_Bounds.Top );
                    p2 = new PointF( m_Bounds.Right, m_Bounds.Top );
                    p3 = new PointF( m_Bounds.Left, m_Bounds.Bottom );
                    p4 = new PointF( m_Bounds.Right, m_Bounds.Bottom );

                    g.DrawLine( p, p1, p2 );
                    g.DrawLine( p, p2, p4 );
                    g.DrawLine( p, p1, p3 );
                    g.DrawLine( p, p3, p4 );
                }
            }

            p.Dispose();
        }
    }
}