public bool NoContactCertainty(IConvex2D shape)
        {
            float minA = 0;
            float maxA = 0;
            float minB = 0;
            float maxB = 0;

            // Only check up & right normals for an AABB since down & left are the same axes

            shape.Project(Vector2.up, ref minA, ref maxA);
            this.Project(Vector2.up, ref minB, ref maxB);

            // Check if the polygon projections are currentlty NOT intersecting
            if (Utility.IntervalDistance(minA, maxA, minB, maxB) > 0)
            {
                return(true);
            }

            shape.Project(Vector2.right, ref minA, ref maxA);
            this.Project(Vector2.right, ref minB, ref maxB);

            // Check if the polygon projections are currentlty NOT intersecting
            if (Utility.IntervalDistance(minA, maxA, minB, maxB) > 0)
            {
                return(true);
            }

            return(false);
        }
Пример #2
0
        /// <summary>
        /// Adds a unit.
        /// </summary>
        public void Add(T unit, IConvex2D shape)
        {
            foreach (var cell in _getOrCreateSupercover(shape))
            {
                cell.Add(new UnitWrapper(unit, shape));
            }

            Count++;
        }
        /// <summary>
        /// Enumerates all cells that are in the supercover of shape and creates a new cell if that cell was null
        /// </summary>
        protected IEnumerable <TCell> _getOrCreateSupercover(IConvex2D shape)
        {
            foreach (var location in shape.Supercover(this))
            {
                if (_cells[location.x, location.y] == null)
                {
                    _cells[location.x, location.y] = _createNewCell(location);
                }

                yield return(_cells[location.x, location.y]);
            }
        }
        /// <summary>
        /// Adds a unit.
        /// </summary>
        public void Add(TKey key, T unit, IConvex2D shape)
        {
            UnitWrapper wrapper = new UnitWrapper(unit, shape);

            foreach (var cell in _getOrCreateSupercover(shape))
            {
                cell.Add(key, wrapper);
            }

            wrappers.Add(key, wrapper);
            Count++;
        }
        /// <summary>
        /// Enumarates all objects that overlap with shape
        /// </summary>
        public IEnumerable <T> Contact(IConvex2D shape)
        {
            // Increment our query number to prevent yielding a unit multiple times if it spans more than one cell
            _queryNumber++;

            foreach (Vector2Int cellIndex in shape.Supercover(this))
            {
                if (_cells[cellIndex.x, cellIndex.y] != null)
                {
                    foreach (var wrapper in _cells[cellIndex.x, cellIndex.y].Contact(shape, (u) => true, _queryNumber))
                    {
                        yield return(wrapper.Unit);
                    }
                }
            }
        }
        /// <summary>
        /// Returns the first object found that contacts shape for which a predicate evaluates to true. It might speak an alien language to us humans.
        /// </summary>
        public T FirstContactWhich(IConvex2D shape, Predicate <T> predicate)
        {
            _queryNumber++;

            foreach (Vector2Int cellIndex in shape.Supercover(this))
            {
                if (_cells[cellIndex.x, cellIndex.y] != null)
                {
                    foreach (var wrapper in _cells[cellIndex.x, cellIndex.y].Contact(shape, predicate, _queryNumber))
                    {
                        return(wrapper.Unit);
                    }
                }
            }

            return(default(T));
        }
        /// <summary>
        /// Updates a unit's position / shape
        /// </summary>
        public void Update(TKey key, IConvex2D newShape)
        {
            UnitWrapper wrapper = wrappers[key];

            foreach (var cell in _getOrCreateSupercover(wrapper.Shape))
            {
                cell.Remove(key);
            }

            var newWrapper = new UnitWrapper(wrapper.Unit, newShape);

            foreach (var cell in _getOrCreateSupercover(newShape))
            {
                cell.Add(key, newWrapper);
            }
            wrappers[key] = newWrapper;
        }
            /// <summary>
            /// Returns all units in this cell that contact shape
            /// </summary>
            public IEnumerable <UnitWrapper> Contact(IConvex2D shape, Predicate <T> predicate, int queryNumber)
            {
                foreach (var wrapper in _unitWrappers)
                {
                    // Make sure to check each unit only once. Certain shapes might span multiple cells.
                    if (!wrapper.Once(queryNumber))
                    {
                        continue;
                    }

                    if (!shape.NoContactCertainty(wrapper.Shape) &&
                        !wrapper.Shape.NoContactCertainty(shape) &&
                        predicate(wrapper.Unit))
                    {
                        yield return(wrapper);
                    }
                }
            }
        public bool NoContactCertainty(IConvex2D shape)
        {
            float minA = 0;
            float maxA = 0;
            float minB = 0;
            float maxB = 0;

            Vector2 normal = new Vector2(-(w.y - v.y), w.x - v.x).normalized;

            shape.Project(normal, ref minA, ref maxA);
            this.Project(normal, ref minB, ref maxB);

            // Check if the polygon projections are currentlty NOT intersecting
            if (Utility.IntervalDistance(minA, maxA, minB, maxB) > 0)
            {
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Returns the first object found that contacts shape. It might speak an alien language to us humans.
        /// </summary>
        public T FirstContact(IConvex2D shape)
        {
            _queryNumber++;

            int cellsSearched = 0;

            foreach (Vector2Int cellIndex in shape.Supercover(this))
            {
                cellsSearched++;
                if (_cells[cellIndex.x, cellIndex.y] != null)
                {
                    foreach (var wrapper in _cells[cellIndex.x, cellIndex.y].Contact(shape, (u) => true, _queryNumber))
                    {
                        return(wrapper.Unit);
                    }
                }
            }

            AverageCellsSearched = Mathf.Lerp(AverageCellsSearched, cellsSearched, 0.5f);
            return(default(T));
        }
        /// <summary>
        /// Enumarates all objects that overlap with a convex shape and for which a predicate evaluates to true
        /// </summary>
        public IEnumerable <T> ContactWhich(IConvex2D shape, Predicate <T> predicate)
        {
            // Increment our query number to prevent yielding a unit multiple times if it spans more than one cell
            _queryNumber++;
            int cellsSearched = 0;
            int unitsAcc      = 0;

            foreach (Vector2Int cellIndex in shape.Supercover(this))
            {
                cellsSearched++;
                if (_cells[cellIndex.x, cellIndex.y] != null)
                {
                    unitsAcc += _cells[cellIndex.x, cellIndex.y].Count;
                    foreach (var wrapper in _cells[cellIndex.x, cellIndex.y].Contact(shape, predicate, _queryNumber))
                    {
                        yield return(wrapper.Unit);
                    }
                }
            }

            AverageCellsSearched = Mathf.Lerp(AverageCellsSearched, cellsSearched, 0.5f);
            AverageUnitsPerCell  = (float)unitsAcc / cellsSearched;
        }
Пример #12
0
 public bool NoContactCertainty(IConvex2D shape)
 {
     return(this.shape.NoContactCertainty(shape));
 }
Пример #13
0
 public bool NoContactCertainty(IConvex2D shape)
 {
     return(shape.DistanceSquared(new Vector2(x, y)) > 0);
 }
Пример #14
0
 public void UpdateShape(int key, IConvex2D shape)
 {
     _grid.Update(key, shape);
 }
            private int _lastQueryNumber; // Keeps track of the last query number that has been made to prevent duplicate results

            public UnitWrapper(T unit, IConvex2D shape)
            {
                Shape = shape;
                Unit  = unit;
            }
Пример #16
0
 public CachedShape(IGridDimensions2D grid, IConvex2D shape)
 {
     this.shape      = shape;
     this.supercover = shape.Supercover(grid).ToArray();
 }
 /// <summary>
 /// No SAT here
 /// A shape doesn't touch a circle when it's closest distance to the circle's center is greater than the circle's radius
 /// </summary>
 public bool NoContactCertainty(IConvex2D shape)
 {
     return(shape.DistanceSquared(center) > radius * radius);
 }