Пример #1
0
        public void Add(T newObject)
        {
            if (values == null)
            {
                if (newObject.IsInArea(childAreaA.myArea))
                {
                    childAreaA.Add(newObject);
                }
                if (newObject.IsInArea(childAreaB.myArea))
                {
                    childAreaB.Add(newObject);
                }
                return;
            }

            if (heldValues < ValuesSize)
            {
                values[heldValues] = newObject;
                heldValues++;
                return;
            }

            //Need to split this into multiple areas.
            //int middleX = (myArea.MaxX + myArea.MinX) / 2;
            //int middleY = (myArea.MaxY + myArea.MinY) / 2;
            //First get the area ACTUALLY being used, to try to help skip empty areas
            int minX = myArea.MaxX, minY = myArea.MaxY, maxX = myArea.MinX, maxY = myArea.MinY;

            for (byte i = 0; i < ValuesSize; i++)
            {
                SimpleArea nextArea = values[i].GetMaxArea();
                minX = Math.Min(minX, nextArea.MinX);
                maxX = Math.Max(maxX, nextArea.MaxX);
                minY = Math.Min(minY, nextArea.MinY);
                maxY = Math.Max(maxY, nextArea.MaxY);
            }
            int middleX = (maxX + minX) / 2;
            int middleY = (maxY + minY) / 2;

            //Split the current area through the 'center' (technically the center of the USED area)
            SimpleArea newLeft, newRight, newForward, newBack;

            newLeft.MinX    = myArea.MinX;
            newLeft.MaxX    = middleX;
            newLeft.MinY    = myArea.MinY;
            newLeft.MaxY    = myArea.MaxY;
            newRight.MinX   = middleX + 1;
            newRight.MaxX   = myArea.MaxX;
            newRight.MinY   = myArea.MinY;
            newRight.MaxY   = myArea.MaxY;
            newForward.MinX = myArea.MinX;
            newForward.MaxX = myArea.MaxX;
            newForward.MinY = myArea.MinY;
            newForward.MaxY = middleY;
            newBack.MinX    = myArea.MinX;
            newBack.MaxX    = myArea.MaxX;
            newBack.MinY    = middleY + 1;
            newBack.MaxY    = myArea.MaxY;

            byte leftCount = 0, rightCount = 0, forwardCount = 0, backCount = 0;

            T[] leftItems    = new T[100];
            T[] rightItems   = new T[100];
            T[] forwardItems = new T[100];
            T[] backItems    = new T[100];

            //Sort items into the area(s) they exist in
            for (byte i = 0; i < ValuesSize; i++)
            {
                T nextItem = values[i];
                if (nextItem.IsInArea(newLeft))
                {
                    leftItems[leftCount++] = nextItem;
                }
                if (nextItem.IsInArea(newRight))
                {
                    rightItems[rightCount++] = nextItem;
                }
                if (nextItem.IsInArea(newForward))
                {
                    forwardItems[forwardCount++] = nextItem;
                }
                if (nextItem.IsInArea(newBack))
                {
                    backItems[backCount++] = nextItem;
                }
            }
            byte maxYCount = Math.Max(forwardCount, backCount);
            byte maxXCount = Math.Max(leftCount, rightCount);

            //Decide which axis to split this across. If neither splits items better, try to make split areas closer to square.
            if (maxYCount > maxXCount || (maxYCount == maxXCount && (maxX - minX >= maxY - minY)))
            {
                childAreaA = new AreaNode <T>(newLeft, leftItems);
                childAreaB = new AreaNode <T>(newRight, rightItems);
            }
            else
            {
                childAreaA = new AreaNode <T>(newForward, forwardItems);
                childAreaB = new AreaNode <T>(newBack, backItems);
            }
            values = null;

            //Area split. Recurse to insert items into child areas now.
            Add(newObject);
        }
Пример #2
0
 public AreaTree(SimpleArea maxArea)
 {
     rootNode = new AreaNode <T>(maxArea);
 }