예제 #1
0
        public void RebuildBottomUp()
        {
            int[] nodes = new int[m_nodeCount];
            int count = 0;

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

                if (m_nodes[i].IsLeaf())
                {
                    m_nodes[i].parentOrNext = b2TreeNode.b2_nullNode;
                    nodes[count] = i;
                    ++count;
                }
                else
                {
                    FreeNode(i);
                }
            }

            while (count > 1)
            {
                float minCost = b2Settings.b2_maxFloat;
                int iMin = -1, jMin = -1;
                for (int i = 0; i < count; ++i)
                {
                    b2AABB aabbi = m_nodes[nodes[i]].aabb;

                    for (int j = i + 1; j < count; ++j)
                    {
                        b2AABB aabbj = m_nodes[nodes[j]].aabb;
                        b2AABB b = new b2AABB();
                        b.Combine(aabbi, aabbj);
                        float cost = b.GetPerimeter();
                        if (cost < minCost)
                        {
                            iMin = i;
                            jMin = j;
                            minCost = cost;
                        }
                    }
                }

                int index1 = nodes[iMin];
                int index2 = nodes[jMin];
                b2TreeNode child1 = m_nodes[index1];
                b2TreeNode child2 = m_nodes[index2];

                int parentIndex = AllocateNode();
                b2TreeNode parent = m_nodes[parentIndex];
                parent.child1 = index1;
                parent.child2 = index2;
                parent.height = 1 + Math.Max(child1.height, child2.height);
                parent.aabb.Combine(child1.aabb, child2.aabb);
                parent.parentOrNext = b2TreeNode.b2_nullNode;

                child1.parentOrNext = parentIndex;
                child2.parentOrNext = parentIndex;

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

            m_root = nodes[0];

            Validate();
        }
예제 #2
0
        public void RebuildBottomUp()
        {
            int[] nodes = new int[m_nodeCount];
            int   count = 0;

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

                if (m_nodes[i].IsLeaf())
                {
                    m_nodes[i].parentOrNext = b2TreeNode.b2_nullNode;
                    nodes[count]            = i;
                    ++count;
                }
                else
                {
                    FreeNode(i);
                }
            }

            while (count > 1)
            {
                float minCost = b2Settings.b2_maxFloat;
                int   iMin = -1, jMin = -1;
                for (int i = 0; i < count; ++i)
                {
                    b2AABB aabbi = m_nodes[nodes[i]].aabb;

                    for (int j = i + 1; j < count; ++j)
                    {
                        b2AABB aabbj = m_nodes[nodes[j]].aabb;
                        b2AABB b     = new b2AABB();
                        b.Combine(aabbi, aabbj);
                        float cost = b.GetPerimeter();
                        if (cost < minCost)
                        {
                            iMin    = i;
                            jMin    = j;
                            minCost = cost;
                        }
                    }
                }

                int        index1 = nodes[iMin];
                int        index2 = nodes[jMin];
                b2TreeNode child1 = m_nodes[index1];
                b2TreeNode child2 = m_nodes[index2];

                int        parentIndex = AllocateNode();
                b2TreeNode parent      = m_nodes[parentIndex];
                parent.child1 = index1;
                parent.child2 = index2;
                parent.height = 1 + Math.Max(child1.height, child2.height);
                parent.aabb.Combine(child1.aabb, child2.aabb);
                parent.parentOrNext = b2TreeNode.b2_nullNode;

                child1.parentOrNext = parentIndex;
                child2.parentOrNext = parentIndex;

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

            m_root = nodes[0];

            Validate();
        }
예제 #3
0
        public void InsertLeaf(int leaf)
        {
            ++m_insertionCount;

            if (m_root == b2TreeNode.b2_nullNode)
            {
                m_root = leaf;
                m_nodes[m_root].parentOrNext = b2TreeNode.b2_nullNode;
                return;
            }

            // Find the best sibling for this node
            b2AABB leafAABB = m_nodes[leaf].aabb;
            int index = m_root;
            while (m_nodes[index].IsLeaf() == false)
            {
                int child1 = m_nodes[index].child1;
                int child2 = m_nodes[index].child2;

                float area = m_nodes[index].aabb.GetPerimeter();

                b2AABB combinedAABB = new b2AABB();
                combinedAABB.Combine(m_nodes[index].aabb, leafAABB);
                float combinedArea = combinedAABB.GetPerimeter();

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

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

                // Cost of descending into child1
                float cost1;
                if (m_nodes[child1].IsLeaf())
                {
                    b2AABB aabb = new b2AABB();
                    aabb.Combine(leafAABB, m_nodes[child1].aabb);
                    cost1 = aabb.GetPerimeter() + inheritanceCost;
                }
                else
                {
                    b2AABB aabb = new b2AABB();
                    aabb.Combine(leafAABB, m_nodes[child1].aabb);
                    float oldArea = m_nodes[child1].aabb.GetPerimeter();
                    float newArea = aabb.GetPerimeter();
                    cost1 = (newArea - oldArea) + inheritanceCost;
                }

                // Cost of descending into child2
                float cost2;
                if (m_nodes[child2].IsLeaf())
                {
                    b2AABB aabb = new b2AABB();
                    aabb.Combine(leafAABB, m_nodes[child2].aabb);
                    cost2 = aabb.GetPerimeter() + inheritanceCost;
                }
                else
                {
                    b2AABB aabb = new b2AABB();
                    aabb.Combine(leafAABB, m_nodes[child2].aabb);
                    float oldArea = m_nodes[child2].aabb.GetPerimeter();
                    float newArea = aabb.GetPerimeter();
                    cost2 = newArea - oldArea + inheritanceCost;
                }

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

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

            int sibling = index;

            // Create a new parent.
            int oldParent = m_nodes[sibling].parentOrNext;
            int newParent = AllocateNode();
            m_nodes[newParent].parentOrNext = oldParent;
            m_nodes[newParent].userData = null;
            m_nodes[newParent].aabb.Combine(leafAABB, m_nodes[sibling].aabb);
            m_nodes[newParent].height = m_nodes[sibling].height + 1;

            if (oldParent != b2TreeNode.b2_nullNode)
            {
                // The sibling was not the root.
                if (m_nodes[oldParent].child1 == sibling)
                {
                    m_nodes[oldParent].child1 = newParent;
                }
                else
                {
                    m_nodes[oldParent].child2 = newParent;
                }

                m_nodes[newParent].child1 = sibling;
                m_nodes[newParent].child2 = leaf;
                m_nodes[sibling].parentOrNext = newParent;
                m_nodes[leaf].parentOrNext = newParent;
            }
            else
            {
                // The sibling was the root.
                m_nodes[newParent].child1 = sibling;
                m_nodes[newParent].child2 = leaf;
                m_nodes[sibling].parentOrNext = newParent;
                m_nodes[leaf].parentOrNext = newParent;
                m_root = newParent;
            }

            // Walk back up the tree fixing heights and AABBs
            index = m_nodes[leaf].parentOrNext;
            while (index != b2TreeNode.b2_nullNode)
            {
                index = Balance(index);

                int child1 = m_nodes[index].child1;
                int child2 = m_nodes[index].child2;

                Debug.Assert(child1 != b2TreeNode.b2_nullNode);
                Debug.Assert(child2 != b2TreeNode.b2_nullNode);

                m_nodes[index].height = 1 + Math.Max(m_nodes[child1].height, m_nodes[child2].height);
                m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb);

                index = m_nodes[index].parentOrNext;
            }

            //Validate();
        }
예제 #4
0
        public void InsertLeaf(int leaf)
        {
            ++m_insertionCount;

            if (m_root == b2TreeNode.b2_nullNode)
            {
                m_root = leaf;
                m_nodes[m_root].parentOrNext = b2TreeNode.b2_nullNode;
                return;
            }

            // Find the best sibling for this node
            b2AABB leafAABB = m_nodes[leaf].aabb;
            int    index    = m_root;

            while (m_nodes[index].IsLeaf() == false)
            {
                int child1 = m_nodes[index].child1;
                int child2 = m_nodes[index].child2;

                float area = m_nodes[index].aabb.GetPerimeter();

                b2AABB combinedAABB = new b2AABB();
                combinedAABB.Combine(m_nodes[index].aabb, leafAABB);
                float combinedArea = combinedAABB.GetPerimeter();

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

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

                // Cost of descending into child1
                float cost1;
                if (m_nodes[child1].IsLeaf())
                {
                    b2AABB aabb = new b2AABB();
                    aabb.Combine(leafAABB, m_nodes[child1].aabb);
                    cost1 = aabb.GetPerimeter() + inheritanceCost;
                }
                else
                {
                    b2AABB aabb = new b2AABB();
                    aabb.Combine(leafAABB, m_nodes[child1].aabb);
                    float oldArea = m_nodes[child1].aabb.GetPerimeter();
                    float newArea = aabb.GetPerimeter();
                    cost1 = (newArea - oldArea) + inheritanceCost;
                }

                // Cost of descending into child2
                float cost2;
                if (m_nodes[child2].IsLeaf())
                {
                    b2AABB aabb = new b2AABB();
                    aabb.Combine(leafAABB, m_nodes[child2].aabb);
                    cost2 = aabb.GetPerimeter() + inheritanceCost;
                }
                else
                {
                    b2AABB aabb = new b2AABB();
                    aabb.Combine(leafAABB, m_nodes[child2].aabb);
                    float oldArea = m_nodes[child2].aabb.GetPerimeter();
                    float newArea = aabb.GetPerimeter();
                    cost2 = newArea - oldArea + inheritanceCost;
                }

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

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

            int sibling = index;

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

            m_nodes[newParent].parentOrNext = oldParent;
            m_nodes[newParent].userData     = null;
            m_nodes[newParent].aabb.Combine(leafAABB, m_nodes[sibling].aabb);
            m_nodes[newParent].height = m_nodes[sibling].height + 1;

            if (oldParent != b2TreeNode.b2_nullNode)
            {
                // The sibling was not the root.
                if (m_nodes[oldParent].child1 == sibling)
                {
                    m_nodes[oldParent].child1 = newParent;
                }
                else
                {
                    m_nodes[oldParent].child2 = newParent;
                }

                m_nodes[newParent].child1     = sibling;
                m_nodes[newParent].child2     = leaf;
                m_nodes[sibling].parentOrNext = newParent;
                m_nodes[leaf].parentOrNext    = newParent;
            }
            else
            {
                // The sibling was the root.
                m_nodes[newParent].child1     = sibling;
                m_nodes[newParent].child2     = leaf;
                m_nodes[sibling].parentOrNext = newParent;
                m_nodes[leaf].parentOrNext    = newParent;
                m_root = newParent;
            }

            // Walk back up the tree fixing heights and AABBs
            index = m_nodes[leaf].parentOrNext;
            while (index != b2TreeNode.b2_nullNode)
            {
                index = Balance(index);

                int child1 = m_nodes[index].child1;
                int child2 = m_nodes[index].child2;

                Debug.Assert(child1 != b2TreeNode.b2_nullNode);
                Debug.Assert(child2 != b2TreeNode.b2_nullNode);

                m_nodes[index].height = 1 + Math.Max(m_nodes[child1].height, m_nodes[child2].height);
                m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb);

                index = m_nodes[index].parentOrNext;
            }

            //Validate();
        }