Пример #1
0
        void ForceInsert(int id, int nodeId, RotRect bounds, Point xy)
        {
            var node = _nodes[nodeId];

            _items[id]._bounds = bounds;
            _items[id]._xy     = xy;
            _items[id]._node   = nodeId;
            _items[id]._next   = -1;
            if (node._itemCount == 0)
            {
                _nodes[nodeId]._firstChild = id;
            }
            else
            {
                var itemId = node._firstChild;
                var item   = _items[itemId];
                for (var i = 1; i < node._itemCount; i++)
                {
                    itemId = item._next;
                    item   = _items[itemId];
                }
                _items[itemId]._next = id;
            }
            _nodes[nodeId]._itemCount++;
        }
Пример #2
0
        public void Insert(int id, Vector2 xy, Vector2 size, float angle = 0, Vector2 origin = default)
        {
            var bounds = new RotRect(xy, size, angle, origin);
            var aabb   = bounds.AABB;
            var center = aabb.Center;
            int nodeId = Insert(id, 0, bounds, center);

            TrySubdivide(nodeId);
            _nodesToGrow.Add(nodeId);
        }
Пример #3
0
 int Insert(int id, int nodeId, RotRect bounds, Point xy)
 {
     do
     {
         var n = _nodes[nodeId];
         if (n._itemCount < 0)
         {
             nodeId = xy.X < n._cX ? xy.Y < n._cY ? n._firstChild : n._firstChild + 3 : xy.Y < n._cY ? n._firstChild + 1 : n._firstChild + 2;
             continue;
         }
         ForceInsert(id, nodeId, bounds, xy);
         return(nodeId);
     } while (true);
 }
Пример #4
0
        public IEnumerable <Rectangle> Nodes(RotRect area = default)
        {
            if (area.Size == Vector2.Zero)
            {
                area = new RotRect(_bounds);
            }
            _toProcess.Push(0);
            do
            {
                var nId = _toProcess.Pop();
                var n   = _nodes[nId];
                yield return(n._bounds);

                if (n._itemCount < 0)
                {
                    var node2 = _nodes[n._firstChild];
                    if (area.Intersects(node2._bounds))
                    {
                        _toProcess.Push(n._firstChild);
                    }
                    node2 = _nodes[n._firstChild + 1];
                    if (area.Intersects(node2._bounds))
                    {
                        _toProcess.Push(n._firstChild + 1);
                    }
                    node2 = _nodes[n._firstChild + 2];
                    if (area.Intersects(node2._bounds))
                    {
                        _toProcess.Push(n._firstChild + 2);
                    }
                    node2 = _nodes[n._firstChild + 3];
                    if (area.Intersects(node2._bounds))
                    {
                        _toProcess.Push(n._firstChild + 3);
                    }
                    continue;
                }
            } while (_toProcess.Count > 0);
            yield break;
        }
Пример #5
0
        /// <summary>Query and return the items intersecting <paramref name="rect"/>.</summary>
        public IEnumerable <int> Query(RotRect rect)
        {
            _toProcess.Push(0);
            do
            {
                var nId = _toProcess.Pop();
                var n   = _nodes[nId];
                if (n._itemCount < 0)
                {
                    var node2 = _nodes[n._firstChild];
                    if (rect.Intersects(node2._bounds))
                    {
                        _toProcess.Push(n._firstChild);
                    }
                    node2 = _nodes[n._firstChild + 1];
                    if (rect.Intersects(node2._bounds))
                    {
                        _toProcess.Push(n._firstChild + 1);
                    }
                    node2 = _nodes[n._firstChild + 2];
                    if (rect.Intersects(node2._bounds))
                    {
                        _toProcess.Push(n._firstChild + 2);
                    }
                    node2 = _nodes[n._firstChild + 3];
                    if (rect.Intersects(node2._bounds))
                    {
                        _toProcess.Push(n._firstChild + 3);
                    }
                    continue;
                }
                if (n._itemCount > 0)
                {
                    var item = _items[n._firstChild];
                    if (rect.Contains(n._bounds))
                    {
                        //do {
                        //    yield return item._id;
                        //    if (item._next < 0)
                        //        break;
                        //    item = _items[item._next];
                        //} while (true);
                        var itemId = n._firstChild;
                        for (var i = 0; i < n._itemCount; i++)
                        {
                            item = _items[itemId];
                            yield return(item._id);

                            itemId = item._next;
                        }
                    }
                    else
                    {
                        do
                        {
                            if (rect.Intersects(item._bounds))
                            {
                                yield return(item._id);
                            }
                            if (item._next < 0)
                            {
                                break;
                            }
                            item = _items[item._next];
                        } while (true);
                    }
                }
            } while (_toProcess.Count > 0);
            yield break;
        }
Пример #6
0
        /// <summary>Updates position of <paramref name="id"/> in the tree.</summary>
        /// <returns>True if <paramref name="id"/> has been updated, otherwise false.</returns>
        public bool Update(int id, Vector2 xy, Vector2 size, float angle = 0, Vector2 origin = default)
        {
            var bounds     = new RotRect(xy, size, angle, origin);
            var aabb       = bounds.AABB;
            var center     = aabb.Center;
            var item       = _items[id];
            var node       = _nodes[item._node];
            int halfWidth  = _bounds.Width >> node._depth,
                halfHeight = _bounds.Height >> node._depth;
            var bounds2    = new Rectangle(node._cX - halfWidth, node._cY - halfHeight, halfWidth << 1, halfHeight << 1);

            if (bounds2.Contains(center) || node._parent == -1)
            {
                _items[id]._bounds = bounds;
                _items[id]._xy     = center;
                _nodesToGrow.Add(item._node);
                return(true);
            }
            if (node._firstChild == id)
            {
                _nodes[item._node]._firstChild = item._next;
            }
            else
            {
                var prevItem = node._firstChild;
                var curItem  = _items[prevItem]._next;
                for (var i = 0; i < node._itemCount; i++)
                {
                    if (curItem == id)
                    {
                        _items[prevItem]._next = _items[curItem]._next;
                        break;
                    }
                    prevItem = curItem;
                    curItem  = _items[curItem]._next;
                }
            }
            _nodes[item._node]._itemCount--;
            _nodesToGrow.Add(item._node);
            var nodeId = item._node;

            do
            {
                if (node._parent < 0)
                {
                    break;
                }
                var parentNode = _nodes[node._parent];
                halfWidth  = _bounds.Width >> parentNode._depth;
                halfHeight = _bounds.Height >> parentNode._depth;
                bounds2    = new Rectangle(parentNode._cX - halfWidth, parentNode._cY - halfHeight, halfWidth << 1, halfHeight << 1);
                if (bounds2.Contains(center))
                {
                    nodeId = node._parent;
                    break;
                }
                nodeId = node._parent;
                node   = _nodes[nodeId];
            } while (true);
            var nId2 = Insert(id, nodeId, bounds, center);

            TrySubdivide(nId2);
            _nodesToGrow.Add(nId2);
            return(true);
        }