Exemple #1
0
    /// <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);
    }