Example #1
0
 public VolumeTree(SimpleVolume maxVolume)
 {
     rootNode = new VolumeNode <T>(maxVolume);
 }
Example #2
0
        public void Add(T newObject)
        {
            if (values == null)
            {
                if (newObject.IsInVolume(childVolumeA.myVolume))
                {
                    childVolumeA.Add(newObject);
                }
                if (newObject.IsInVolume(childVolumeB.myVolume))
                {
                    childVolumeB.Add(newObject);
                }
                return;
            }

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

            int minX = myVolume.MaxX, minY = myVolume.MaxY, minZ = myVolume.MaxZ,
                maxX = myVolume.MinX, maxY = myVolume.MinY, maxZ = myVolume.MinZ;

            for (byte i = 0; i < ValuesSize; i++)
            {
                SimpleVolume nextVolume = values[i].GetMaxVolume();
                minX = Math.Min(minX, nextVolume.MinX);
                maxX = Math.Max(maxX, nextVolume.MaxX);
                minY = Math.Min(minY, nextVolume.MinY);
                maxY = Math.Max(maxY, nextVolume.MaxY);
                minZ = Math.Min(minZ, nextVolume.MinZ);
                maxZ = Math.Max(maxZ, nextVolume.MaxZ);
            }
            int middleX = (maxX + minX) / 2;
            int middleY = (maxY + minY) / 2;
            int middleZ = (maxZ + minZ) / 2;

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

            newLeft.MinX    = myVolume.MinX;
            newLeft.MaxX    = middleX;
            newLeft.MinY    = myVolume.MinY;
            newLeft.MaxY    = myVolume.MaxY;
            newLeft.MinZ    = myVolume.MinZ;
            newLeft.MaxZ    = myVolume.MaxZ;
            newRight.MinX   = middleX + 1;
            newRight.MaxX   = myVolume.MaxX;
            newRight.MinY   = myVolume.MinY;
            newRight.MaxY   = myVolume.MaxY;
            newRight.MinZ   = myVolume.MinZ;
            newRight.MaxZ   = myVolume.MaxZ;
            newForward.MinX = myVolume.MinX;
            newForward.MaxX = myVolume.MaxX;
            newForward.MinY = myVolume.MinY;
            newForward.MaxY = middleY;
            newForward.MinZ = myVolume.MinZ;
            newForward.MaxZ = myVolume.MaxZ;
            newBack.MinX    = myVolume.MinX;
            newBack.MaxX    = myVolume.MaxX;
            newBack.MinY    = middleY + 1;
            newBack.MaxY    = myVolume.MaxY;
            newBack.MinZ    = myVolume.MinZ;
            newBack.MaxZ    = myVolume.MaxZ;
            newTop.MinX     = myVolume.MinX;
            newTop.MaxX     = myVolume.MaxX;
            newTop.MinY     = myVolume.MinY;
            newTop.MaxY     = myVolume.MaxY;
            newTop.MinZ     = myVolume.MinZ;
            newTop.MaxZ     = middleZ;
            newBottom.MinX  = myVolume.MinX;
            newBottom.MaxX  = myVolume.MaxX;
            newBottom.MinY  = myVolume.MinY;
            newBottom.MaxY  = myVolume.MaxY;
            newBottom.MinZ  = middleZ + 1;
            newBottom.MaxZ  = myVolume.MaxZ;

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

            T[] leftItems    = new T[100];
            T[] rightItems   = new T[100];
            T[] forwardItems = new T[100];
            T[] backItems    = new T[100];
            T[] topItems     = new T[100];
            T[] bottomItems  = 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.IsInVolume(newLeft))
                {
                    leftItems[leftCount++] = nextItem;
                }
                if (nextItem.IsInVolume(newRight))
                {
                    rightItems[rightCount++] = nextItem;
                }
                if (nextItem.IsInVolume(newForward))
                {
                    forwardItems[forwardCount++] = nextItem;
                }
                if (nextItem.IsInVolume(newBack))
                {
                    backItems[backCount++] = nextItem;
                }
                if (nextItem.IsInVolume(newTop))
                {
                    topItems[topCount++] = nextItem;
                }
                if (nextItem.IsInVolume(newBottom))
                {
                    bottomItems[bottomCount++] = nextItem;
                }
            }
            byte maxYCount = Math.Max(forwardCount, backCount);
            byte maxXCount = Math.Max(leftCount, rightCount);
            byte maxZCount = Math.Max(topCount, bottomCount);

            if (maxYCount < maxZCount ||                                      //Is Y obviously better to split than Z
                (maxZCount == maxYCount && (maxZ - minZ <= maxY - minY)) ||   //Is Y less-obviously better-or-equal to split than Z
                maxXCount < maxZCount ||                                      //Is X obviously better to split than Z
                (maxZCount == maxXCount && (maxZ - minZ <= maxX - minX)))     //Is X less-obviously better-or-equal to split than Z
            {
                if (maxYCount > maxXCount ||                                  //Is X obviously better to split than Y
                    (maxYCount == maxXCount && (maxX - minX >= maxY - minY))) //Is X less-obviously better-or-equal to split than Y
                {
                    //Split on X
                    childVolumeA = new VolumeNode <T>(newLeft, leftItems);
                    childVolumeB = new VolumeNode <T>(newRight, rightItems);
                }
                else
                {
                    //Split on Y
                    childVolumeA = new VolumeNode <T>(newForward, forwardItems);
                    childVolumeB = new VolumeNode <T>(newBack, backItems);
                }
            }
            else
            {
                //Split on Z
                childVolumeA = new VolumeNode <T>(newTop, topItems);
                childVolumeB = new VolumeNode <T>(newBottom, bottomItems);
            }
            values = null;

            Add(newObject);
        }