/// <summary>
        /// Determines if a cell is on the edges of a cell collections
        /// </summary>
        /// <param name="cellID">The ID of the cell</param>
        /// <param name="cellularFloor">The CellularFloorBaseGeometry to which this cell belongs</param>
        /// <param name="collection">Cell ID collection</param>
        /// <returns>true for being on the edge false for not being on the edge</returns>
        private static bool onEdge(int cellID, CellularFloorBaseGeometry cellularFloor, HashSet <int> collection)
        {
            var index = cellularFloor.FindIndex(cellID);

            if (index.I == 0 || index.I == cellularFloor.GridWidth - 1 || index.J == 0 || index.J == cellularFloor.GridHeight - 1)
            {
                return(true);
            }
            int iMin = (index.I == 0) ? 0 : index.I - 1;
            int iMax = (index.I == cellularFloor.GridWidth - 1) ? cellularFloor.GridWidth - 1 : index.I + 1;
            int jMin = (index.J == 0) ? 0 : index.J - 1;
            int jMax = (index.J == cellularFloor.GridHeight - 1) ? cellularFloor.GridHeight - 1 : index.J + 1;

            for (int i = iMin; i <= iMax; i++)
            {
                for (int j = jMin; j <= jMax; j++)
                {
                    if (cellularFloor.ContainsCell(i, j))
                    {
                        if (!collection.Contains(cellularFloor.Cells[i, j].ID))
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
        /// <summary>
        /// Extracts the edges of a collection of cells
        /// </summary>
        /// <param name="cellularFloor">The CellularFloorBaseGeometry to which the cells belong</param>
        /// <param name="collection">A collection of cells to find its edges</param>
        /// <returns>A collection of cell indices on the edge</returns>
        public static HashSet <Index> GetIndexEdgeOfField(CellularFloorBaseGeometry cellularFloor, HashSet <Cell> collection)
        {
            HashSet <Index> edge = new HashSet <Index>();

            foreach (var item in collection)
            {
                Index index = cellularFloor.FindIndex(item);
                if (CellUtility.onEdge(index, cellularFloor, collection))
                {
                    edge.Add(index);
                }
            }
            return(edge);
        }
        /// <summary>
        /// Creats an instance of the CollisionAnalyzer. For internal use only.
        /// </summary>
        /// <param name="point">The agent or target location</param>
        /// <param name="cell">The cell to which the point belongs</param>
        /// <param name="cellularFloor">The CellularFloorBaseGeometry which includes the agent or target</param>
        /// <param name="barrierType">Barrier type</param>
        internal CollisionAnalyzer(UV point, Cell cell, CellularFloorBaseGeometry cellularFloor, BarrierType barrierType)
        {
            this.CollisionOccured = false;
            this.Location         = point;
            Index index = cellularFloor.FindIndex(cell);
            int   I     = index.I + 2;

            //int I = index.I + 1;
            I = Math.Min(I, cellularFloor.GridWidth - 1);
            int J = index.J + 2;

            //int J = index.J + 1;
            J       = Math.Min(J, cellularFloor.GridHeight - 1);
            index.I = Math.Max(0, index.I - 1);
            index.J = Math.Max(0, index.J - 1);
            double DistanceSquared = double.PositiveInfinity;

            for (int i = index.I; i <= I; i++)
            {
                for (int j = index.J; j <= J; j++)
                {
                    switch (barrierType)
                    {
                    case BarrierType.Visual:
                        if (cellularFloor.Cells[i, j].VisualOverlapState == OverlapState.Outside)
                        {
                            foreach (int item in cellularFloor.Cells[i, j].VisualBarrierEdgeIndices)
                            {
                                double d = point.GetDistanceSquared(cellularFloor.VisualBarrierEdges[item]);
                                if (d < DistanceSquared)
                                {
                                    DistanceSquared = d;
                                    Barrrier        = cellularFloor.VisualBarrierEdges[item];
                                }
                            }
                        }
                        break;

                    case BarrierType.Physical:
                        if (cellularFloor.Cells[i, j].PhysicalOverlapState != OverlapState.Outside)
                        {
                            foreach (int item in cellularFloor.Cells[i, j].PhysicalBarrierEdgeIndices)
                            {
                                double d = point.GetDistanceSquared(cellularFloor.PhysicalBarrierEdges[item]);
                                if (d < DistanceSquared)
                                {
                                    DistanceSquared = d;
                                    Barrrier        = cellularFloor.PhysicalBarrierEdges[item];
                                }
                            }
                        }
                        break;

                    case BarrierType.Field:
                        if (cellularFloor.Cells[i, j].BarrierBufferOverlapState != OverlapState.Inside)
                        {
                            foreach (int item in cellularFloor.Cells[i, j].FieldBarrierEdgeIndices)
                            {
                                double d = point.GetDistanceSquared(cellularFloor.FieldBarrierEdges[item]);
                                if (d < DistanceSquared)
                                {
                                    DistanceSquared = d;
                                    Barrrier        = cellularFloor.FieldBarrierEdges[item];
                                }
                            }
                        }
                        break;
                    }
                }
            }
            if (!double.IsPositiveInfinity(DistanceSquared) &&
                this.Barrrier != null)
            {
                bool isEndpoint = false;
                this.ClosestPointOnBarrier    = point.GetClosestPoint(this.Barrrier, ref isEndpoint);
                this.IsClosestPointAnEndPoint = isEndpoint;
                this.NormalizedRepulsion      = this.Location - this.ClosestPointOnBarrier;
                this.DistanceToBarrier        = this.NormalizedRepulsion.GetLength();
                this.NormalizedRepulsion     /= this.DistanceToBarrier;
            }
        }