/// <summary>Add a new item to the index, with the specified bounds.</summary>
        /// <param name="bounds">The bounds of the item.</param>
        /// <param name="item">The item.</param>
        /// <exception cref="T:System.ArgumentException">The item is already stored in the index.</exception>
        public void Add(TRectangle bounds, T item)
        {
            if (Contains(item))
            {
                throw new ArgumentException("Entry is already in the index.", "item");
            }

            // Extend bounds.
            bounds.Inflate(_boundExtension, _boundExtension);

            // Add to each cell the element's bounds intersect with.
            foreach (var cell in ComputeCells(bounds))
            {
                // Create the quad tree for that cell if it doesn't yet exist.
                if (!_cells.ContainsKey(cell.Item1))
                {
                    // No need to extend again, we already did.
                    _cells.Add(
                        cell.Item1,
                        new Collections.DynamicQuadTree <T>(
                            _maxEntriesPerNode,
                            _minNodeBounds,
                            0f,
                            0f,
                            _packetizer,
                            _depacketizer));
                }

                // Convert the item bounds to the tree's local coordinate space.
                var relativeBounds = bounds;
                relativeBounds.Offset(cell.Item2);

                // And add the item to the tree.
// ReSharper disable RedundantCast Necessary for FarCollections.
                _cells[cell.Item1].Add((Math.RectangleF)relativeBounds, item);
// ReSharper restore RedundantCast
            }

            // Store element itself for future retrieval (removals, item lookup).
            _entryBounds.Add(item, bounds);
        }
        /// <summary>
        ///     Update an entry by changing its bounds. If the item is not stored in the index, this will return <code>false</code>
        ///     .
        /// </summary>
        /// <param name="newBounds">The new bounds of the item.</param>
        /// <param name="delta">The amount by which the object moved.</param>
        /// <param name="item">The item for which to update the bounds.</param>
        /// <returns>
        ///     <c>true</c> if the update was successful; <c>false</c> otherwise.
        /// </returns>
        public bool Update(TRectangle newBounds, Vector2 delta, T item)
        {
            // Check if we have that entry, if not add it.
            if (!Contains(item))
            {
                return(false);
            }

            // Get the old bounds.
            var oldBounds = _entryBounds[item];

            // Nothing to do if our approximation in the tree still contains the item.
            if (oldBounds.Contains(newBounds))
            {
                return(false);
            }

            // Estimate movement by bounds delta to predict position and
            // extend the bounds accordingly, to avoid tree updates.
            delta.X *= _movingBoundMultiplier;
            delta.Y *= _movingBoundMultiplier;
            var absDeltaX = delta.X < 0 ? -delta.X : delta.X;
            var absDeltaY = delta.Y < 0 ? -delta.Y : delta.Y;

            newBounds.Width += (int)absDeltaX;
            if (delta.X < 0)
            {
                newBounds.X += (int)delta.X;
            }
            newBounds.Height += (int)absDeltaY;
            if (delta.Y < 0)
            {
                newBounds.Y += (int)delta.Y;
            }

            // Extend bounds.
            newBounds.Inflate(_boundExtension, _boundExtension);

            // Figure out what changed (the delta in cells).

            // Because we already did the bound extensions the update method in the
            // related quad trees would just do superfluous work, so instead we can
            // just remove and re-insert the entries where necessary. This also makes
            // this function a lot simpler.

            /*
             *
             * var oldCells = new HashSet<Tuple<ulong, TPoint>>(ComputeCells(oldBounds));
             * var newCells = new HashSet<Tuple<ulong, TPoint>>(ComputeCells(newBounds));
             *
             * // Get all cells that the entry no longer is in.
             * var removedCells = new HashSet<Tuple<ulong, TPoint>>(oldCells);
             * removedCells.ExceptWith(newCells);
             * foreach (var cell in removedCells)
             * {
             *  // Remove from the tree.
             *  _entries[cell.Item1].Remove(item);
             *
             *  // Clean up: remove the tree if it's empty.
             *  if (_entries[cell.Item1].Count == 0)
             *  {
             *      _entries.Remove(cell.Item1);
             *  }
             * }
             *
             * // Get all the cells the entry now is in.
             * var addedCells = new HashSet<Tuple<ulong, TPoint>>(newCells);
             * addedCells.ExceptWith(oldCells);
             * foreach (var cell in addedCells)
             * {
             *  // Create the quad tree for that cell if it doesn't yet exist.
             *  if (!_entries.ContainsKey(cell.Item1))
             *  {
             *      // No need to extend again, we already did.
             *      _entries.Add(cell.Item1, new Collections.QuadTree<T>(_maxEntriesPerNode, _minNodeBounds, 0f, 0f));
             *  }
             *
             *  // Convert the item bounds to the tree's local coordinate space.
             *  var relativeBounds = newBounds;
             *  relativeBounds.Offset(cell.Item2);
             *
             *  // And add the item to the tree.
             *  _entries[cell.Item1].Add((Math.RectangleF)relativeBounds, item);
             * }
             *
             * // Get all cells the entry still is in.
             * oldCells.ExceptWith(addedCells);
             * oldCells.ExceptWith(removedCells);
             * foreach (var cell in oldCells)
             * {
             *  // Convert the item bounds to the tree's local coordinate space.
             *  var relativeBounds = newBounds;
             *  relativeBounds.Offset(cell.Item2);
             *
             *  // And update the item to the tree.
             *  _entries[cell.Item1].Update((Math.RectangleF)relativeBounds, Vector2.Zero, item);
             * }
             *
             * /*/

            // Remove from old cells.
            foreach (var cell in ComputeCells(oldBounds))
            {
                Collections.DynamicQuadTree <T> tree;
                _cells.TryGetValue(cell.Item1, out tree);
                if (tree != null)
                {
                    tree.Remove(item);
                }
            }

            // Add to new cells.
            foreach (var cell in ComputeCells(newBounds))
            {
                // Create the quad tree for that cell if it doesn't yet exist.
                if (!_cells.ContainsKey(cell.Item1))
                {
                    // No need to extend again, we already did.
                    _cells.Add(
                        cell.Item1,
                        new Collections.DynamicQuadTree <T>(
                            _maxEntriesPerNode,
                            _minNodeBounds,
                            0f,
                            0f,
                            _packetizer,
                            _depacketizer));
                }

                // Convert the item bounds to the tree's local coordinate space.
                var relativeBounds = newBounds;
                relativeBounds.Offset(cell.Item2);

                // And add the item to the tree.
// ReSharper disable RedundantCast Necessary for FarCollections.
                _cells[cell.Item1].Add((Math.RectangleF)relativeBounds, item);
// ReSharper restore RedundantCast
            }

            //*/

            // Store the new item bounds.
            _entryBounds[item] = newBounds;

            return(true);
        }