Пример #1
0
 public void MarkRebalanceIfNeeded(KdTreeNode <T> node)
 {
     if (!node.rebalance.Added && IsNodeUnbalanced(node))
     {
         EnqueueRebalanceOnce(node);
     }
 }
Пример #2
0
 private void TraverseOverlapping(KdTreeNode <T> node, AaRect rect, Action <T> action)
 {
     if (node.type == NodeType.Leaf)
     {
         var holder = node.leaf.holder;
         while (holder != null)
         {
             if (AaRect.Overlaps(rect, holder.fitRect))
             {
                 action(holder.body);
             }
             holder = holder.sibling.next;
         }
     }
     else
     {
         var pos = node.DetermineInnerNodePosition(rect);
         if (pos != ChildPosition.More)
         {
             TraverseOverlapping(node.inner.nodeLess, rect, action);
         }
         if (pos != ChildPosition.Less)
         {
             TraverseOverlapping(node.inner.nodeMore, rect, action);
         }
         TraverseOverlapping(node.inner.nodeBoth, rect, action);
     }
 }
Пример #3
0
        private void ConvertToInnerMaybe(KdTree <T> tree)
        {
            if (count <= 1)
            {
                return;
            }

            bool  successX = AttemptAxis(Axis.X, tree.tempHolderList, out var middleCountX, out var pivotX);
            bool  successY = AttemptAxis(Axis.Y, tree.tempHolderList, out var middleCountY, out var pivotY);
            Axis  foundAxis;
            int   middleCount;
            float pivot;

            if (successX && (!successY || middleCountX < middleCountY))
            {
                middleCount = middleCountX;
                foundAxis   = Axis.X;
                pivot       = pivotX;
            }
            else if (successY)
            {
                middleCount = middleCountY;
                foundAxis   = Axis.Y;
                pivot       = pivotY;
            }
            else
            {
                return;
            }


            if (middleCount >= count * 2 / 3)
            {
                return;
            }


            type           = NodeType.Inner;
            inner.axis     = foundAxis;
            inner.pivot    = pivot;
            inner.nodeBoth = tree.MakeLeafNode(this);
            inner.nodeLess = tree.MakeLeafNode(this);
            inner.nodeMore = tree.MakeLeafNode(this);

            var holder = leaf.holder;

            leaf.holder = null;
            while (holder != null)
            {
                var            nextHolder = holder.sibling.next;
                KdTreeNode <T> newParent  = DetermineInnerNode(holder);
                holder.AddToHolderList(newParent);
                newParent.count++;
                holder = nextHolder;
            }

            PostProcessNewChildNode(tree, inner.nodeLess);
            PostProcessNewChildNode(tree, inner.nodeBoth);
            PostProcessNewChildNode(tree, inner.nodeMore);
        }
Пример #4
0
 private bool IsNodeUnbalanced(KdTreeNode <T> node)
 {
     if (node.type == NodeType.Inner)
     {
         int sideThreshold   = node.count * 2 / 3;
         int middleThreshold = node.count * 1 / 3;
         if (node.count <= 1)
         {
             return(true);
         }
         if (node.inner.nodeLess.count > sideThreshold)
         {
             return(true);
         }
         if (node.inner.nodeMore.count > sideThreshold)
         {
             return(true);
         }
         if (node.inner.nodeBoth.count > middleThreshold)
         {
             return(true);
         }
         return(false);
     }
     return(node.count > 2);
 }
Пример #5
0
        private void AddAndRefreshInternal(KdTreeHolder <T> holder)
        {
            AssertConsistency();
            KdTreeNode <T> fittingLeaf = DetermineFittingLeaf(holder);

            AddInternal(holder, fittingLeaf);
            RefreshAndMarkParents(fittingLeaf);
            AssertConsistency();
        }
Пример #6
0
 private void RefreshAndMarkParents(KdTreeNode <T> node)
 {
     while (node != null)
     {
         node.RefreshBounds();
         MarkRebalanceIfNeeded(node);
         node = node.parent;
     }
 }
Пример #7
0
 internal void DisposeNode(KdTreeNode <T> node)
 {
     RemoveFromRebalanceQueue(node);
     node.parent         = null;
     node.inner.nodeLess = null;
     node.inner.nodeBoth = null;
     node.inner.nodeMore = null;
     node.leaf.holder    = null;
     allocationCacheNode.Add(node);
 }
Пример #8
0
        private void AddInternal(KdTreeHolder <T> holder, KdTreeNode <T> newParent)
        {
            holder.AddToHolderList(newParent);
            var node = newParent;

            while (node != null)
            {
                node.count++;
                node = node.parent;
            }
        }
Пример #9
0
        internal KdTreeNode <T> MakeLeafNode(KdTreeNode <T> parent)
        {
            var node = Pop(allocationCacheNode) ?? new KdTreeNode <T>();

            node.type        = NodeType.Leaf;
            node.leaf.holder = null;
            node.parent      = parent;
            node.count       = 0;
            node.bounds      = null;
            node.refresh     = 0;
            return(node);
        }
Пример #10
0
        public void AddToHolderList(KdTreeNode <T> newParent)
        {
            KdTreeHolder <T> oldfirst = newParent.leaf.holder;

            newParent.leaf.holder = this;
            if (oldfirst != null)
            {
                oldfirst.sibling.prev = this;
            }
            parent       = newParent;
            sibling.next = oldfirst;
            sibling.prev = null;
        }
Пример #11
0
 private bool EnqueueRebalanceOnce(KdTreeNode <T> node)
 {
     if (node.rebalance.Added)
     {
         return(false);
     }
     node.rebalance = new RebalanceLink <T>()
     {
         prev = rebalanceQueueSentinel.rebalance.prev,
         next = rebalanceQueueSentinel
     };
     node.rebalance.prev.rebalance.next = node;
     node.rebalance.next.rebalance.prev = node;
     return(true);
 }
Пример #12
0
        private void RemoveFromRebalanceQueue(KdTreeNode <T> node)
        {
            var oldprev = node.rebalance.prev;
            var oldnext = node.rebalance.next;

            if (oldprev != null)
            {
                oldprev.rebalance.next = oldnext;
            }
            if (oldnext != null)
            {
                oldnext.rebalance.prev = oldprev;
            }
            node.rebalance.prev = null;
            node.rebalance.next = null;
        }
Пример #13
0
        public void RemoveFromHolderList()
        {
            var oldprev = sibling.prev;
            var oldnext = sibling.next;

            if (oldprev != null)
            {
                oldprev.sibling.next = sibling.next;
            }
            else
            {
                parent.leaf.holder = oldnext;
            }
            if (oldnext != null)
            {
                oldnext.sibling.prev = sibling.prev;
            }
            sibling.prev = null;
            sibling.next = null;
            parent       = null;
        }
Пример #14
0
        private void UpdateAndRefreshInternal(KdTreeHolder <T> holder)
        {
            AssertConsistency();
            if (!holder.Update(this))
            {
                return;
            }
            KdTreeNode <T> oldLeaf = holder.parent;
            KdTreeNode <T> newLeaf = DetermineFittingLeaf(holder);

            if (oldLeaf == newLeaf)
            {
                RefreshAndMarkParents(oldLeaf);
                return;
            }

            AssertConsistency();
            RemoveInternal(holder);
            AddInternal(holder, newLeaf);
            RefreshAndMarkParents(oldLeaf);
            RefreshAndMarkParents(newLeaf);
            AssertConsistency();
        }
Пример #15
0
        private void DisposeChildrenAndMoveHolders(KdTreeNode <T> newLeaf, KdTree <T> tree)
        {
            switch (type)
            {
            case NodeType.Inner:
            {
                DisposeAndMoveHolders(ref inner.nodeLess, newLeaf, tree);
                DisposeAndMoveHolders(ref inner.nodeBoth, newLeaf, tree);
                DisposeAndMoveHolders(ref inner.nodeMore, newLeaf, tree);
            } break;

            case NodeType.Leaf:
            {
                var holder = leaf.holder;
                leaf.holder = null;
                while (holder != null)
                {
                    var next = holder.sibling.next;
                    holder.AddToHolderList(newLeaf);
                    holder = next;
                }
            } break;
            }
        }
Пример #16
0
 public KdTree()
 {
     rebalanceQueueSentinel = new KdTreeNode <T>();
     rebalanceQueueSentinel.rebalance.prev = rebalanceQueueSentinel;
     rebalanceQueueSentinel.rebalance.next = rebalanceQueueSentinel;
 }
Пример #17
0
 private void PostProcessNewChildNode(KdTree <T> tree, KdTreeNode <T> node)
 {
     node.RefreshBounds();
     tree.MarkRebalanceIfNeeded(node);
 }
Пример #18
0
 private void DisposeAndMoveHolders(ref KdTreeNode <T> node, KdTreeNode <T> newLeaf, KdTree <T> tree)
 {
     node.DisposeChildrenAndMoveHolders(newLeaf, tree);
     tree.DisposeNode(node);
     node = null;
 }