/// <summary> /// Inserts a leaf node with the specified `aabb` values and associated `data`. /// </summary> /// <returns>The index of the inserted node.</returns> public Node <T> Add(T data, AABB insertedAABB) { // create new node and fatten its aabb var leafNode = new Node <T>(insertedAABB, data, null); leafNode.aabb.inflate(FattenDelta, FattenDelta); leafNode.invHeight = 0; NumLeaves++; if (_root == null) { _root = leafNode; return(leafNode); } // find best sibling to insert the leaf var leafAABB = leafNode.aabb; var combinedAABB = new AABB(); Node <T> left; Node <T> right; var node = _root; while (!node.isLeaf()) { bool breakWhile = false; switch (InsertStrategy.choose(leafAABB, node)) { case InsertChoice.PARENT: breakWhile = true; break; case InsertChoice.DESCEND_LEFT: node = node.left; break; case InsertChoice.DESCEND_RIGHT: node = node.right; break; } if (breakWhile) { break; } } var sibling = node; // create a new parent var oldParent = sibling.parent; combinedAABB.asUnionOf(leafAABB, sibling.aabb); var newParent = new Node <T>(combinedAABB.x, combinedAABB.y, combinedAABB.width, combinedAABB.height, default(T), oldParent); newParent.invHeight = sibling.invHeight + 1; // the sibling was not the root if (oldParent != null) { if (oldParent.left == sibling) { oldParent.left = newParent; } else { oldParent.right = newParent; } } else { // the sibling was the root _root = newParent; } newParent.left = sibling; newParent.right = leafNode; sibling.parent = newParent; leafNode.parent = newParent; // walk back up the tree fixing heights and AABBs node = leafNode.parent; while (node != null) { node = Balance(node); left = node.left; right = node.right; Assert(left != null); Assert(right != null); node.invHeight = 1 + (Math.Max(left.invHeight, right.invHeight)); node.aabb.asUnionOf(left.aabb, right.aabb); node = node.parent; } Validate(); return(leafNode); }