Beispiel #1
0
        private void RemoveFromCell(T obj, int xIdx, int yIdx)
        {
            UGridRow row = rows[yIdx];

            T elt     = row.cells[xIdx];
            T prevElt = null;

            while (elt.ID != obj.ID)
            {
                prevElt = elt;
                elt     = (T)elt.NextElt;

                if (elt == null)
                {
                    throw new Exception("Element not found");
                }
            }

            if (prevElt == null)
            {
                row.cells[xIdx] = (T)elt.NextElt;
            }
            else
            {
                prevElt.NextElt = elt.NextElt;
            }

            --row.eltCount;
        }
Beispiel #2
0
        private void InsertToCell(T obj, int xIdx, int yIdx)
        {
            UGridRow row = rows[yIdx];

            obj.NextElt     = row.cells[xIdx];
            row.cells[xIdx] = obj;
            ++row.eltCount;
        }
Beispiel #3
0
        /// <summary>
        /// Moves an element in the grid from the former position to the new one.
        /// </summary>
        /// <param name="obj">The object to move</param>
        /// <param name="fromX">The current position of the object in the grid</param>
        /// <param name="fromY">The current position of the object in the grid</param>
        /// <param name="toX">The new position of the object in the grid</param>
        /// <param name="toY">The new position of the object in the grid</param>
        public void Move(T obj, float fromX, float fromY, float toX, float toY)
        {
            int oldCol = GridLocalToCellCol(fromX);
            int oldRow = GridLocalToCellRow(fromY);
            int newCol = GridLocalToCellCol(toX);
            int newRow = GridLocalToCellRow(toY);

            UGridRow row = rows[oldRow];

            if (oldCol != newCol || oldRow != newRow)
            {
                RemoveFromCell(obj, oldCol, oldRow);
                InsertToCell(obj, newCol, newRow);
            }
        }
Beispiel #4
0
        // Returns all the element IDs that intersect the specified rectangle excluding
        // elements with the specified ID to omit.
        public List <T> Query(float lft, float btm, float rgt, float top, int omitEltID = int.MinValue)
        {
            // expand the query by the size of the elements
            // since we use the bottom left point to represent elements, we expand
            // the bottom left of the query to catch any elements with an origin
            // outside the query but with a bounding box inside it
            lft -= _eltWidth;
            btm -= _eltHeight;

            // Find the cells that intersect the search query.
            int minX = GridLocalToCellCol(lft);
            int minY = GridLocalToCellRow(btm);
            int maxX = GridLocalToCellCol(rgt);
            int maxY = GridLocalToCellRow(top);

            AABB query = new AABB(lft, top, rgt, btm);

            _queryResults.Clear();
            for (int y = minY; y <= maxY; ++y)
            {
                UGridRow row = rows[y];
                if (row.eltCount == 0)
                {
                    continue;
                }

                for (int x = minX; x <= maxX; ++x)
                {
                    T elt = row.cells[x];
                    while (elt != null)
                    {
                        if (PointInRect(elt, in query) && elt.ID != omitEltID)
                        {
                            _queryResults.Add(elt);
                        }
                        elt = (T)elt.NextElt;
                    }
                }
            }
            return(_queryResults);
        }
Beispiel #5
0
        // Returns a new grid storing elements that have a uniform upper-bound size. Because
        // all elements are treated uniformly-sized for the sake of search queries, each one
        // can be stored as a single point in the grid.
        public UGrid(int eWidth, int eHeight, float cWidth, float cHeight,
                     int gridWidth, int gridHeight)
        {
            _numRows       = (int)(gridHeight / cHeight) + 1;
            _numCols       = (int)(gridWidth / cWidth) + 1;
            _eltWidth      = eWidth;
            _eltHeight     = eHeight;
            _invCellWidth  = 1 / cWidth;
            _invCellHeight = 1 / cHeight;
            _width         = gridWidth;
            _height        = gridHeight;



            rows = new UGridRow[_numRows];
            for (int i = 0; i < _numRows; i++)
            {
                rows[i]       = new UGridRow();
                rows[i].cells = new T[_numCols];
            }
        }
Beispiel #6
0
        /// <summary>
        /// Calls <see cref="IUniformGridVisitor.Grid(float, float, float, float)"/> with the grid data
        /// Then traverses the whole grid and calls <see cref="IUniformGridVisitor.Cell(IUGridElt, int, int, float, float)"/>
        /// on any non-empty cells.
        /// </summary>
        public void Traverse(IUniformGridVisitor visitor)
        {
            visitor.Grid(_width, _height, 1f / _invCellWidth, 1f / _invCellHeight);

            for (int y = 0; y < _numRows; ++y)
            {
                UGridRow row = rows[y];
                if (row.eltCount == 0)
                {
                    continue;
                }

                for (int x = 0; x < _numCols; ++x)
                {
                    if (row.cells[x] != null)
                    {
                        visitor.Cell(row.cells[x], x, y, 1f / _invCellWidth, 1f / _invCellHeight);
                    }
                }
            }
        }