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); }
public AreaTree(SimpleArea maxArea) { rootNode = new AreaNode <T>(maxArea); }