예제 #1
0
        /// <summary>
        /// Build an optimal tree. Very expensive. For testing.
        /// </summary>
        public void RebuildBottomUp()
        {
            int[] nodes = new int[_nodeCount];
            int   count = 0;

            // Build array of leaves. Free the rest.
            for (int i = 0; i < _nodeCapacity; ++i)
            {
                if (_nodes[i].Height < 0)
                {
                    // free node in pool
                    continue;
                }

                if (_nodes[i].IsLeaf())
                {
                    _nodes[i].ParentOrNext = NullNode;
                    nodes[count]           = i;
                    ++count;
                }
                else
                {
                    FreeNode(i);
                }
            }

            while (count > 1)
            {
                FP  minCost = Settings.MaxFP;
                int iMin = -1, jMin = -1;
                for (int i = 0; i < count; ++i)
                {
                    AABB AABBi = _nodes[nodes[i]].AABB;

                    for (int j = i + 1; j < count; ++j)
                    {
                        AABB AABBj = _nodes[nodes[j]].AABB;
                        AABB b     = new AABB();
                        b.Combine(ref AABBi, ref AABBj);
                        FP cost = b.Perimeter;
                        if (cost < minCost)
                        {
                            iMin    = i;
                            jMin    = j;
                            minCost = cost;
                        }
                    }
                }

                int          index1 = nodes[iMin];
                int          index2 = nodes[jMin];
                TreeNode <T> child1 = _nodes[index1];
                TreeNode <T> child2 = _nodes[index2];

                int          parentIndex = AllocateNode();
                TreeNode <T> parent      = _nodes[parentIndex];
                parent.Child1 = index1;
                parent.Child2 = index2;
                parent.Height = 1 + Math.Max(child1.Height, child2.Height);
                parent.AABB.Combine(ref child1.AABB, ref child2.AABB);
                parent.ParentOrNext = NullNode;

                child1.ParentOrNext = parentIndex;
                child2.ParentOrNext = parentIndex;

                nodes[jMin] = nodes[count - 1];
                nodes[iMin] = parentIndex;
                --count;
            }

            _root = nodes[0];

            Validate();
        }
예제 #2
0
        public void RebuildBottomUp()
        {
            int[] array = new int[this._nodeCount];
            int   i     = 0;

            for (int j = 0; j < this._nodeCapacity; j++)
            {
                bool flag = this._nodes[j].Height < 0;
                if (!flag)
                {
                    bool flag2 = this._nodes[j].IsLeaf();
                    if (flag2)
                    {
                        this._nodes[j].ParentOrNext = -1;
                        array[i] = j;
                        i++;
                    }
                    else
                    {
                        this.FreeNode(j);
                    }
                }
            }
            while (i > 1)
            {
                FP  y    = Settings.MaxFP;
                int num  = -1;
                int num2 = -1;
                for (int k = 0; k < i; k++)
                {
                    AABB aABB = this._nodes[array[k]].AABB;
                    for (int l = k + 1; l < i; l++)
                    {
                        AABB aABB2 = this._nodes[array[l]].AABB;
                        AABB aABB3 = default(AABB);
                        aABB3.Combine(ref aABB, ref aABB2);
                        FP   perimeter = aABB3.Perimeter;
                        bool flag3     = perimeter < y;
                        if (flag3)
                        {
                            num  = k;
                            num2 = l;
                            y    = perimeter;
                        }
                    }
                }
                int          num3      = array[num];
                int          num4      = array[num2];
                TreeNode <T> treeNode  = this._nodes[num3];
                TreeNode <T> treeNode2 = this._nodes[num4];
                int          num5      = this.AllocateNode();
                TreeNode <T> treeNode3 = this._nodes[num5];
                treeNode3.Child1 = num3;
                treeNode3.Child2 = num4;
                treeNode3.Height = 1 + Math.Max(treeNode.Height, treeNode2.Height);
                treeNode3.AABB.Combine(ref treeNode.AABB, ref treeNode2.AABB);
                treeNode3.ParentOrNext = -1;
                treeNode.ParentOrNext  = num5;
                treeNode2.ParentOrNext = num5;
                array[num2]            = array[i - 1];
                array[num]             = num5;
                i--;
            }
            this._root = array[0];
            this.Validate();
        }
예제 #3
0
        private void InsertLeaf(int leaf)
        {
            if (_root == NullNode)
            {
                _root = leaf;
                _nodes[_root].ParentOrNext = NullNode;
                return;
            }

            // Find the best sibling for this node
            AABB leafAABB = _nodes[leaf].AABB;
            int  index    = _root;

            while (_nodes[index].IsLeaf() == false)
            {
                int child1 = _nodes[index].Child1;
                int child2 = _nodes[index].Child2;

                FP area = _nodes[index].AABB.Perimeter;

                AABB combinedAABB = new AABB();
                combinedAABB.Combine(ref _nodes[index].AABB, ref leafAABB);
                FP combinedArea = combinedAABB.Perimeter;

                // Cost of creating a new parent for this node and the new leaf
                FP cost = 2.0f * combinedArea;

                // Minimum cost of pushing the leaf further down the tree
                FP inheritanceCost = 2.0f * (combinedArea - area);

                // Cost of descending into child1
                FP cost1;
                if (_nodes[child1].IsLeaf())
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child1].AABB);
                    cost1 = aabb.Perimeter + inheritanceCost;
                }
                else
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child1].AABB);
                    FP oldArea = _nodes[child1].AABB.Perimeter;
                    FP newArea = aabb.Perimeter;
                    cost1 = (newArea - oldArea) + inheritanceCost;
                }

                // Cost of descending into child2
                FP cost2;
                if (_nodes[child2].IsLeaf())
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child2].AABB);
                    cost2 = aabb.Perimeter + inheritanceCost;
                }
                else
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child2].AABB);
                    FP oldArea = _nodes[child2].AABB.Perimeter;
                    FP newArea = aabb.Perimeter;
                    cost2 = newArea - oldArea + inheritanceCost;
                }

                // Descend according to the minimum cost.
                if (cost < cost1 && cost1 < cost2)
                {
                    break;
                }

                // Descend
                if (cost1 < cost2)
                {
                    index = child1;
                }
                else
                {
                    index = child2;
                }
            }

            int sibling = index;

            // Create a new parent.
            int oldParent = _nodes[sibling].ParentOrNext;
            int newParent = AllocateNode();

            _nodes[newParent].ParentOrNext = oldParent;
            _nodes[newParent].UserData     = default(T);
            _nodes[newParent].AABB.Combine(ref leafAABB, ref _nodes[sibling].AABB);
            _nodes[newParent].Height = _nodes[sibling].Height + 1;

            if (oldParent != NullNode)
            {
                // The sibling was not the root.
                if (_nodes[oldParent].Child1 == sibling)
                {
                    _nodes[oldParent].Child1 = newParent;
                }
                else
                {
                    _nodes[oldParent].Child2 = newParent;
                }

                _nodes[newParent].Child1     = sibling;
                _nodes[newParent].Child2     = leaf;
                _nodes[sibling].ParentOrNext = newParent;
                _nodes[leaf].ParentOrNext    = newParent;
            }
            else
            {
                // The sibling was the root.
                _nodes[newParent].Child1     = sibling;
                _nodes[newParent].Child2     = leaf;
                _nodes[sibling].ParentOrNext = newParent;
                _nodes[leaf].ParentOrNext    = newParent;
                _root = newParent;
            }

            // Walk back up the tree fixing heights and AABBs
            index = _nodes[leaf].ParentOrNext;
            while (index != NullNode)
            {
                index = Balance(index);

                int child1 = _nodes[index].Child1;
                int child2 = _nodes[index].Child2;

                Debug.Assert(child1 != NullNode);
                Debug.Assert(child2 != NullNode);

                _nodes[index].Height = 1 + Math.Max(_nodes[child1].Height, _nodes[child2].Height);
                _nodes[index].AABB.Combine(ref _nodes[child1].AABB, ref _nodes[child2].AABB);

                index = _nodes[index].ParentOrNext;
            }

            //Validate();
        }
예제 #4
0
        private void InsertLeaf(int leaf)
        {
            bool flag = this._root == -1;

            if (flag)
            {
                this._root = leaf;
                this._nodes[this._root].ParentOrNext = -1;
            }
            else
            {
                AABB aABB = this._nodes[leaf].AABB;
                int  num  = this._root;
                while (!this._nodes[num].IsLeaf())
                {
                    int  child     = this._nodes[num].Child1;
                    int  child2    = this._nodes[num].Child2;
                    FP   perimeter = this._nodes[num].AABB.Perimeter;
                    AABB aABB2     = default(AABB);
                    aABB2.Combine(ref this._nodes[num].AABB, ref aABB);
                    FP   perimeter2 = aABB2.Perimeter;
                    FP   x          = 2f * perimeter2;
                    FP   y          = 2f * (perimeter2 - perimeter);
                    bool flag2      = this._nodes[child].IsLeaf();
                    FP   fP;
                    if (flag2)
                    {
                        AABB aABB3 = default(AABB);
                        aABB3.Combine(ref aABB, ref this._nodes[child].AABB);
                        fP = aABB3.Perimeter + y;
                    }
                    else
                    {
                        AABB aABB4 = default(AABB);
                        aABB4.Combine(ref aABB, ref this._nodes[child].AABB);
                        FP perimeter3 = this._nodes[child].AABB.Perimeter;
                        FP perimeter4 = aABB4.Perimeter;
                        fP = perimeter4 - perimeter3 + y;
                    }
                    bool flag3 = this._nodes[child2].IsLeaf();
                    FP   y2;
                    if (flag3)
                    {
                        AABB aABB5 = default(AABB);
                        aABB5.Combine(ref aABB, ref this._nodes[child2].AABB);
                        y2 = aABB5.Perimeter + y;
                    }
                    else
                    {
                        AABB aABB6 = default(AABB);
                        aABB6.Combine(ref aABB, ref this._nodes[child2].AABB);
                        FP perimeter5 = this._nodes[child2].AABB.Perimeter;
                        FP perimeter6 = aABB6.Perimeter;
                        y2 = perimeter6 - perimeter5 + y;
                    }
                    bool flag4 = x < fP && fP < y2;
                    if (flag4)
                    {
                        break;
                    }
                    bool flag5 = fP < y2;
                    if (flag5)
                    {
                        num = child;
                    }
                    else
                    {
                        num = child2;
                    }
                }
                int num2         = num;
                int parentOrNext = this._nodes[num2].ParentOrNext;
                int num3         = this.AllocateNode();
                this._nodes[num3].ParentOrNext = parentOrNext;
                this._nodes[num3].UserData     = default(T);
                this._nodes[num3].AABB.Combine(ref aABB, ref this._nodes[num2].AABB);
                this._nodes[num3].Height = this._nodes[num2].Height + 1;
                bool flag6 = parentOrNext != -1;
                if (flag6)
                {
                    bool flag7 = this._nodes[parentOrNext].Child1 == num2;
                    if (flag7)
                    {
                        this._nodes[parentOrNext].Child1 = num3;
                    }
                    else
                    {
                        this._nodes[parentOrNext].Child2 = num3;
                    }
                    this._nodes[num3].Child1       = num2;
                    this._nodes[num3].Child2       = leaf;
                    this._nodes[num2].ParentOrNext = num3;
                    this._nodes[leaf].ParentOrNext = num3;
                }
                else
                {
                    this._nodes[num3].Child1       = num2;
                    this._nodes[num3].Child2       = leaf;
                    this._nodes[num2].ParentOrNext = num3;
                    this._nodes[leaf].ParentOrNext = num3;
                    this._root = num3;
                }
                for (num = this._nodes[leaf].ParentOrNext; num != -1; num = this._nodes[num].ParentOrNext)
                {
                    num = this.Balance(num);
                    int child3 = this._nodes[num].Child1;
                    int child4 = this._nodes[num].Child2;
                    Debug.Assert(child3 != -1);
                    Debug.Assert(child4 != -1);
                    this._nodes[num].Height = 1 + Math.Max(this._nodes[child3].Height, this._nodes[child4].Height);
                    this._nodes[num].AABB.Combine(ref this._nodes[child3].AABB, ref this._nodes[child4].AABB);
                }
            }
        }