Пример #1
0
        protected ExploreCell GetCurrentExploreCell()
        {
            Vec3 curr_pos = Navmesh.Navigator.CurrentPos;

            ExploreCell current_explore_cell = m_ExploreCells.Find(x => x.CellsContains2D(curr_pos));

            if (current_explore_cell == null)
            {
                current_explore_cell = m_ExploreCells.Find(x => x.Contains2D(curr_pos));
            }

            // find nearest explore cell
            if (current_explore_cell == null)
            {
                float min_dist = float.MaxValue;

                foreach (ExploreCell explore_cell in m_ExploreCells)
                {
                    float dist = explore_cell.Position.DistanceSqr(curr_pos);

                    if (dist < min_dist)
                    {
                        current_explore_cell = explore_cell;
                        min_dist             = dist;
                    }
                }
            }

            return(current_explore_cell);
        }
Пример #2
0
        protected HashSet <ExploreCell> GetUnexploredCells(ExploreCell origin_cell)
        {
            using (new ReadLock(DataLock))
            {
                var agent_pos = m_Navigator.CurrentPos;

                // unexplored selector is collecting ALL unexplored cells matching constraints and filter criteria
                UnexploredSelector selector = new UnexploredSelector(ExploreConstraints, ExploreFilter, IgnoreSmall, agent_pos, m_Navmesh);
                Algorihms.Visit <ExploreCell>(origin_cell, MovementFlag.None, -1, null, selector);

                m_CellsToExploreCount = selector.all_cells_count;
                m_ExploredCellsCount  = m_CellsToExploreCount - selector.unexplored_cells.Count;

                // first try all big cells unvisited by anyone (undelayed)
                HashSet <ExploreCell> unexplored_cells_subset = new HashSet <ExploreCell>(selector.unexplored_cells.Where(x => !x.Small && !x.Delayed));

                if (unexplored_cells_subset.Count > 0)
                {
                    return(unexplored_cells_subset);
                }

                // try all big cells unvisited by me
                unexplored_cells_subset = new HashSet <ExploreCell>(selector.unexplored_cells.Where(x => !x.Small));

                if (unexplored_cells_subset.Count > 0)
                {
                    return(unexplored_cells_subset);
                }

                // try all remaining cells
                return(selector.unexplored_cells);
            }
        }
Пример #3
0
        internal virtual Vec3 GetDestinationCellPosition()
        {
            Vec3 hint_pos = HintPos;

            if (!hint_pos.IsEmpty)
            {
                // find nearest unexplored cell to the hint position
                float       min_dist             = float.MaxValue;
                ExploreCell nearest_explore_cell = null;

                foreach (ExploreCell explore_cell in m_ExploreCells)
                {
                    if (explore_cell.Explored)
                    {
                        continue;
                    }

                    float dist = explore_cell.Position.DistanceSqr(hint_pos);

                    if (dist < min_dist)
                    {
                        nearest_explore_cell = explore_cell;
                        min_dist             = dist;
                    }
                }

                return(nearest_explore_cell != null ? nearest_explore_cell.Position : Vec3.Empty);
            }

            return(Vec3.Empty);
        }
Пример #4
0
        protected HashSet <ExploreCell> GetUnexploredCells(ExploreCell origin_cell)
        {
            using (new ReadLock(DataLock))
            {
                UnexploredSelector selector = new UnexploredSelector();
                Algorihms.Visit <ExploreCell>(origin_cell, MovementFlag.None, -1, null, selector);

                m_CellsToExploreCount = selector.all_cells_count;
                m_ExploredCellsCount  = m_CellsToExploreCount - selector.unexplored_cells.Count;

                // first try all big cells unvisited by anyone (undelayed)
                HashSet <ExploreCell> unexplored_cells_subset = new HashSet <ExploreCell>(selector.unexplored_cells.Where(x => !x.Small && !x.Delayed));

                if (unexplored_cells_subset.Count > 0)
                {
                    return(unexplored_cells_subset);
                }

                // try all big cells unvisited by me
                unexplored_cells_subset = new HashSet <ExploreCell>(selector.unexplored_cells.Where(x => !x.Small));

                if (unexplored_cells_subset.Count > 0)
                {
                    return(unexplored_cells_subset);
                }

                // try all remaining cells
                return(selector.unexplored_cells);
            }
        }
Пример #5
0
        internal bool GetCellAt(Vec3 p, out ExploreCell result_cell)
        {
            using (new ReadLock(DataLock))
            {
                result_cell = null;

                if (p.IsZero())
                {
                    return(false);
                }

                foreach (var explore_cell in m_ExploreCells)
                {
                    if (explore_cell.Contains2D(p))
                    {
                        var cells = explore_cell.GetCellsAt(p, test_2d: true, z_tolerance: 0);

                        if (cells.Count() > 0)
                        {
                            result_cell = explore_cell;
                            return(true);
                        }
                    }
                }

                return(false);
            }
        }
Пример #6
0
        protected virtual void OnDeserialize(HashSet <Cell> all_cells, BinaryReader r)
        {
            using (new WriteLock(DataLock))
                using (new WriteLock(InputLock))
                {
                    m_ExploreCells.Clear();

                    m_Enabled = r.ReadBoolean();

                    int explore_cells_count = r.ReadInt32();

                    // pre-allocate explore cells
                    for (int i = 0; i < explore_cells_count; ++i)
                    {
                        ExploreCell explore_cell = new ExploreCell();
                        explore_cell.GlobalId = r.ReadInt32();
                        m_ExploreCells.Add(explore_cell);
                    }

                    foreach (ExploreCell explore_cell in m_ExploreCells)
                    {
                        explore_cell.Deserialize(m_ExploreCells, all_cells, r);
                    }

                    ExploreCell.LastExploreCellGlobalId = r.ReadInt32();

                    m_HintPos = new Vec3(r);
                }
        }
Пример #7
0
        public static void Render(Nav.ExploreCell cell, float radius, PointF trans, PaintEventArgs e, bool draw_connections, bool draw_id)
        {
            DrawRectangle(e.Graphics, Pens.Magenta, trans, cell.Min, cell.Max);

            //DrawString(e.Graphics, Brushes.Black, trans, cell.Position, Math.Round(cell.CellsArea()).ToString(), 14);

            if (cell.Explored)
            {
                //DrawLine(e.Graphics, explored_pen, trans, cell.Min, cell.Max);
                //DrawLine(e.Graphics, explored_pen, trans, new Vec3(cell.Min.X, cell.Max.Y), new Vec3(cell.Max.X, cell.Min.Y));
                FillRectangle(e.Graphics, explored_brush, trans, cell.Min, cell.Max);
            }
            else
            {
                //DrawCircle(e.Graphics, Pens.Red, trans, cell.Position, radius);
                //DrawString(e.Graphics, Brushes.Black, trans, cell.Position, cell.UserData.ToString(), 10);

                if (draw_connections)
                {
                    foreach (Nav.Cell.Neighbour neighbour in cell.Neighbours)
                    {
                        ExploreCell neighbour_cell = (ExploreCell)neighbour.cell;

                        DrawLine(e.Graphics, EXPLORE_CELL_CONNECTION_PEN, trans, cell.Center, neighbour.border_point);
                    }
                }
            }

            if (draw_id)
            {
                DrawString(e.Graphics, Brushes.Black, trans, cell.Position, cell.GlobalId.ToString() + " (" + cell.Id.ToString() + ")", 10);
            }
        }
Пример #8
0
        internal virtual void Deserialize(List <Cell> all_cells, BinaryReader r)
        {
            using (new WriteLock(DataLock))
                using (new WriteLock(InputLock))
                {
                    m_ExploreCells.Clear();
                    m_ExploreCellsDistancer.Clear();

                    m_Enabled = r.ReadBoolean();

                    int explore_cells_count = r.ReadInt32();

                    // pre-allocate explore cells
                    for (int i = 0; i < explore_cells_count; ++i)
                    {
                        ExploreCell explore_cell = new ExploreCell();
                        explore_cell.GlobalId = r.ReadInt32();
                        m_ExploreCells.Add(explore_cell);
                    }

                    m_ExploreCells.Sort(new Cell.CompareByGlobalId());

                    foreach (ExploreCell explore_cell in m_ExploreCells)
                    {
                        explore_cell.Deserialize(m_ExploreCells, all_cells, r);
                    }

                    ExploreCell.LastExploreCellGlobalId = r.ReadInt32();

                    m_ExploreCellsDistancer.Deserialize(r);

                    m_HintPos = new Vec3(r);
                }
        }
Пример #9
0
        protected virtual void OnCellExplored(ExploreCell cell)
        {
            if (cell == null)
            {
                return;
            }

            cell.Explored = true; // this is safe as explore cells cannot be added/removed now
            m_Navmesh.Log("[Nav] Explored cell " + cell.GlobalId + " [progress: " + GetExploredPercent() + "%]!");
        }
Пример #10
0
        private void Add(ExploreCell explore_cell)
        {
            using (new WriteLock(DataLock))
            {
                foreach (ExploreCell e_cell in m_ExploreCells)
                {
                    e_cell.AddNeighbour(explore_cell);
                }

                m_ExploreCells.Add(explore_cell);
            }
        }
Пример #11
0
        protected virtual void OnDeserialize(HashSet <Cell> all_cells, Dictionary <int, Cell> id_to_cell, BinaryReader r)
        {
            m_ExploreCells.Clear();

            m_Enabled = r.ReadBoolean();

            int explore_cells_count = r.ReadInt32();

            // pre-allocate explore cells
            for (int i = 0; i < explore_cells_count; ++i)
            {
                ExploreCell explore_cell = new ExploreCell();
                explore_cell.GlobalId = r.ReadInt32();
                m_ExploreCells.Add(explore_cell);
            }

            foreach (ExploreCell explore_cell in m_ExploreCells)
            {
                explore_cell.Deserialize(m_ExploreCells, all_cells, id_to_cell, r);
            }

            foreach (ExploreCell explore_cell in m_ExploreCells)
            {
                OnExploreCellAdded(explore_cell);
            }

            var dest_cell_global_id = r.ReadInt32();

            if (dest_cell_global_id >= 0)
            {
                m_DestCell = m_ExploreCells.FirstOrDefault(x => x.GlobalId == dest_cell_global_id);
            }

            ExploreCell.LastExploreCellGlobalId = r.ReadInt32();

            m_ExploredCellsCount  = r.ReadInt32();
            m_CellsToExploreCount = r.ReadInt32();

            var explore_constraints_count = r.ReadInt32();
            var exConstraints             = explore_constraints_count > 0 ? new List <AABB>() : null;

            if (exConstraints != null)
            {
                for (int i = 0; i < explore_constraints_count; ++i)
                {
                    exConstraints.Add(new AABB(r));
                }
            }
            m_ExploreConstraints = exConstraints;

            m_HintPos = new Vec3(r);
        }
Пример #12
0
        public static void Render(Nav.Navmesh navmesh, Nav.ExploreCell cell, List <Nav.ExploreCell> all_cells, PointF trans, PaintEventArgs e, bool draw_id)
        {
            foreach (ExploreCell other_cell in all_cells)
            {
                if (cell.Id == other_cell.Id)
                {
                    continue;
                }

                DrawLine(e.Graphics, Pens.Gray, trans, cell.Position, other_cell.Position);
                //DrawString(e.Graphics, Brushes.Black, trans, (cell.Position + other_cell.Position) * 0.5f, Math.Round(navmesh.Explorator.ExploreDistance(cell, other_cell)).ToString(), 8);
            }
        }
Пример #13
0
        private void Add(ExploreCell explore_cell)
        {
            using (m_Navmesh.AcquireReadDataLock())
                using (new WriteLock(DataLock))
                {
                    foreach (ExploreCell e_cell in m_ExploreCells)
                    {
                        e_cell.AddNeighbour(explore_cell);
                    }

                    m_ExploreCells.Add(explore_cell);
                }
        }
Пример #14
0
        private void Add(ExploreCell explore_cell)
        {
            using (m_Navmesh.AcquireReadDataLock())
                using (new WriteLock(DataLock))
                {
                    foreach (ExploreCell e_cell in m_ExploreCells)
                    {
                        e_cell.AddNeighbour(explore_cell);
                    }

                    m_ExploreCells.Add(explore_cell);
                    Interlocked.Exchange(ref m_ForceRefreshExploredPercent, 1);
                }
        }
Пример #15
0
        private void Add(ExploreCell explore_cell)
        {
            using (new WriteLock(DataLock))
            {
                foreach (ExploreCell e_cell in m_ExploreCells)
                {
                    if (e_cell.AddNeighbour(explore_cell))
                    {
                        m_ExploreCellsDistancer.Connect(e_cell.GlobalId, explore_cell.GlobalId, e_cell.Position.Distance2D(explore_cell.Position));
                    }
                }

                m_ExploreCells.Add(explore_cell);
            }
        }
Пример #16
0
        public void OnDestinationReached(destination dest)
        {
            if (dest.type != DestType.Explore)
            {
                return;
            }

            ExploreCell dest_cell = dest.user_data as ExploreCell;

            if (dest_cell != null)
            {
                OnCellExplored(dest_cell);
            }

            SelectNewDestinationCell();
        }
Пример #17
0
        public void OnDestinationReached(DestType type, Vec3 dest)
        {
            if (type != DestType.Explore)
            {
                return;
            }

            ExploreCell dest_cell = m_ExploreCells.FirstOrDefault(x => x.Position.Equals(dest));

            if (dest_cell != null)
            {
                OnCellExplored(dest_cell);
            }

            m_DestCell = GetDestinationCell();
            m_Navigator.SetDestination(GetDestinationCellPosition(), DestType.Explore, ExploreDestPrecision);
        }
Пример #18
0
        public void OnDestinationReached(DestType type, Vec3 dest)
        {
            if (type != DestType.Explore)
            {
                return;
            }

            ExploreCell dest_cell = m_ExploreCells.Find(x => x.Position.Equals(dest));

            if (dest_cell != null)
            {
                OnCellExplored(dest_cell);
            }

            Vec3 next_dest = GetDestinationCellPosition();

            Navmesh.Navigator.SetDestination(next_dest, DestType.Explore);
        }
Пример #19
0
        private void UpdateExploration()
        {
            Vec3 current_pos = m_Navigator.CurrentPos;

            if (current_pos.IsZero())
            {
                return;
            }

            if (!IsDataAvailable)
            {
                m_Navmesh.Log("[Nav] Exploration data unavailable!");
                return;
            }

            if (IsExplored())
            {
                m_Navmesh.Log("[Nav] Exploration finished!");
                m_Navigator.ClearDestination(DestType.Explore);
                return;
            }

            using (new ReadLock(DataLock, true))
            {
                if (m_Navigator.GetDestinationType() < DestType.Explore)
                {
                    m_DestCell = GetDestinationCell();
                    m_Navigator.SetDestination(GetDestinationCellPosition(), DestType.Explore, ExploreDestPrecision);
                    //m_Navmesh.Log("[Nav] Explore dest changed.");
                }

                {
                    // mark cells as explored when passing by close enough
                    ExploreCell current_explore_cell = m_ExploreCells.FirstOrDefault(x => !x.Explored && x.Position.Distance2D(current_pos) < ExploreDestPrecision);

                    if (current_explore_cell != null)
                    {
                        OnCellExplored(current_explore_cell);
                    }
                }

                OnUpdateExploration();
            }
        }
Пример #20
0
        private void SelectNewDestinationCell(ExploreCell curr_explore_cell)
        {
            //using (new Profiler("SelectNewDestinationCell [%t]"))
            {
                var prev_dest_cell = m_DestCell;
                m_DestCell = GetDestinationCell(curr_explore_cell);

                //Trace.WriteLine($"dest explore cell id {m_DestCell?.GlobalId ?? -1} pos {GetDestinationCellPosition()}");

                //using (new Profiler("set explore cell pos as dest [%t]"))
                if (Enabled)
                {
                    m_Navigator.SetDestination(new destination(GetDestinationCellPosition(), DestType.Explore, ExploreDestPrecision, user_data: m_DestCell, stop: false));
                }

                // force reevaluation so connectivity check is performed on selected cell (it is cheaper than checking connectivity for all unexplored cells)
                m_ValidateDestCell = m_DestCell != prev_dest_cell;
            }
        }
Пример #21
0
        public void OnDestinationReached(destination dest)
        {
            if (dest.type != DestType.Explore)
            {
                return;
            }

            ExploreCell dest_cell = dest.user_data as ExploreCell;

            //Trace.WriteLine($"marking explore cell id {dest_cell?.GlobalId ?? -1} as explored");

            if (dest_cell != null)
            {
                Trace.WriteLine($"Explore cell GID {m_DestCell.GlobalId} considered explored because it was reached.");
                OnCellExplored(dest_cell);
            }

            SelectNewDestinationCell(dest_cell);
        }
Пример #22
0
        private void UpdateExploration()
        {
            Vec3 current_pos = Navmesh.Navigator.CurrentPos;

            if (!Enabled || current_pos.IsEmpty)
            {
                return;
            }

            if (!IsDataAvailable)
            {
                Navmesh.Log("[Nav] Exploration data unavailable!");
                return;
            }

            if (IsExplored())
            {
                Navmesh.Log("[Nav] Exploration finished!");
                Navmesh.Navigator.SetDestination(Vec3.Empty, DestType.None);
                return;
            }

            using (new ReadLock(DataLock, true))
            {
                if (Navmesh.Navigator.GetDestinationType() < DestType.Explore)
                {
                    Vec3 dest = GetDestinationCellPosition();
                    Navmesh.Navigator.SetDestination(dest, DestType.Explore);
                    Navmesh.Log("[Nav] Explore dest changed.");
                }

                {
                    // mark cells as explored when passing by close enough
                    ExploreCell current_explore_cell = m_ExploreCells.Find(x => !x.Explored && x.Position.Distance2D(current_pos) < Navmesh.Navigator.ExploreCellPrecision);

                    if (current_explore_cell != null)
                    {
                        OnCellExplored(current_explore_cell);
                    }
                }
            }
        }
Пример #23
0
        protected ExploreCell GetCurrentExploreCell()
        {
            Vec3 curr_pos = m_Navigator.CurrentPos;

            ExploreCell current_explore_cell = m_ExploreCells.FirstOrDefault(x => x.CellsContains2D(curr_pos));

            if (current_explore_cell == null)
            {
                // try explore cells containing current position first
                var potential_explore_cells = m_ExploreCells.Where(x => x.Contains2D(curr_pos));

                if (potential_explore_cells == null)
                {
                    potential_explore_cells = m_ExploreCells; // find nearest explore cell
                }
                if (potential_explore_cells != null)
                {
                    if (potential_explore_cells.Count() == 1)
                    {
                        current_explore_cell = potential_explore_cells.First();
                    }
                    else
                    {
                        float min_dist = float.MaxValue;

                        foreach (var explore_cell in potential_explore_cells)
                        {
                            float dist = explore_cell.Cells.Select(x => x.Distance(curr_pos)).Min();

                            if (dist < min_dist)
                            {
                                current_explore_cell = explore_cell;
                                min_dist             = dist;
                            }
                        }
                    }
                }
            }

            return(current_explore_cell);
        }
Пример #24
0
        public bool AddNeighbour(ExploreCell explore_cell)
        {
            if (!Overlaps2D(explore_cell, true))
                return false;

            foreach (Cell cell in Cells)
            {
                foreach (Cell other_cell in explore_cell.Cells)
                {
                    if (cell.Equals(other_cell) || cell.Neighbours.Exists(x => x.cell.Equals(other_cell)))
                    {
                        Neighbours.Add(new Neighbour(explore_cell, null, MovementFlag.None));
                        explore_cell.Neighbours.Add(new Neighbour(this, null, MovementFlag.None));
                        
                        return true;
                    }
                }
            }

            return false;
        }
Пример #25
0
        protected virtual void OnDeserialize(HashSet <Cell> all_cells, Dictionary <int, Cell> id_to_cell, BinaryReader r)
        {
            using (new WriteLock(DataLock))
                using (new WriteLock(InputLock))
                {
                    m_ExploreCells.Clear();

                    m_Enabled = r.ReadBoolean();

                    int explore_cells_count = r.ReadInt32();

                    // pre-allocate explore cells
                    for (int i = 0; i < explore_cells_count; ++i)
                    {
                        ExploreCell explore_cell = new ExploreCell();
                        explore_cell.GlobalId = r.ReadInt32();
                        m_ExploreCells.Add(explore_cell);
                    }

                    foreach (ExploreCell explore_cell in m_ExploreCells)
                    {
                        explore_cell.Deserialize(m_ExploreCells, all_cells, id_to_cell, r);
                    }

                    var dest_cell_global_id = r.ReadInt32();
                    if (dest_cell_global_id >= 0)
                    {
                        m_DestCell = m_ExploreCells.FirstOrDefault(x => x.GlobalId == dest_cell_global_id);
                    }

                    ExploreCell.LastExploreCellGlobalId = r.ReadInt32();

                    m_ExploredCellsCount  = r.ReadInt32();
                    m_CellsToExploreCount = r.ReadInt32();

                    m_HintPos = new Vec3(r);
                }
        }
Пример #26
0
        public bool AddNeighbour(ExploreCell explore_cell)
        {
            if (!Overlaps2D(explore_cell, true))
            {
                return(false);
            }

            foreach (Cell cell in Cells)
            {
                foreach (Cell other_cell in explore_cell.Cells)
                {
                    if (cell.Equals(other_cell) || cell.Neighbours.Exists(x => x.cell.Equals(other_cell)))
                    {
                        Neighbours.Add(new Neighbour(explore_cell, Vec3.ZERO, MovementFlag.None));
                        explore_cell.Neighbours.Add(new Neighbour(this, Vec3.ZERO, MovementFlag.None));

                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #27
0
        protected List <int> GetUnexploredCellsId(ExploreCell origin_cell)
        {
            using (new ReadLock(DataLock))
            {
                List <ExploreCell> unexplored_cells     = m_ExploreCells.FindAll(x => !x.Explored);
                List <ExploreCell> big_unexplored_cells = unexplored_cells.FindAll(x => !x.Small);

                List <int> unexplored_cells_id = null;

                // explore small cells only when all other cells were explored
                if (big_unexplored_cells.Count == 0)
                {
                    unexplored_cells_id = unexplored_cells.Select(x => x.GlobalId).ToList();
                }
                else
                {
                    unexplored_cells_id = big_unexplored_cells.Select(x => x.GlobalId).ToList();
                }

                List <int> potential_cells_id = m_ExploreCellsDistancer.GetConnectedTo(origin_cell.GlobalId);

                return(potential_cells_id.Intersect(unexplored_cells_id).ToList()); // consider only unexplored
            }
        }
Пример #28
0
        public virtual bool IsExplored()
        {
            using (new ReadLock(DataLock))
            {
                if (!IsDataAvailable)
                {
                    return(false);
                }

                ExploreCell current_explore_cell = GetCurrentExploreCell();

                if (current_explore_cell == null)
                {
                    return(true);
                }

                if (!current_explore_cell.Explored)
                {
                    return(false);
                }

                return(GetUnexploredCells(current_explore_cell).Count == 0);
            }
        }
Пример #29
0
        public static void FindExplorePath2Opt(ExploreCell start_cell, List <ExploreCell> explore_cells, CellsDistancer distances, ref List <Vec3> path)
        {
            path.Clear();

            if (start_cell == null)
            {
                return;
            }

            List <int> cells_id_in_start_cell_network = distances.GetConnectedTo(start_cell.GlobalId);

            List <ExploreCell> best_tour = explore_cells.FindAll(c => cells_id_in_start_cell_network.Contains(c.GlobalId));

            best_tour.RemoveAll(c => c.Explored || c.Neighbours.Count == 0);
            if (start_cell.Explored)
            {
                best_tour.Insert(0, start_cell);
            }

            if (best_tour.Count == 1)
            {
                path.Add(best_tour[0].Position);
                return;
            }

            float best_dist = GetTravelDistance(best_tour, distances);


            if (best_tour.Count < 90)
            {
                // based on http://en.wikipedia.org/wiki/2-opt

                while (true)
                {
                    bool better_found = false;

                    for (int i = 1; i < best_tour.Count - 1; ++i)
                    {
                        for (int k = i + 1; k < best_tour.Count; ++k)
                        {
                            float new_dist = Swap2OptDistance(best_tour, distances, i, k);

                            if (new_dist < best_dist)
                            {
                                Swap2Opt(ref best_tour, i, k);
                                best_dist = new_dist;

                                better_found = true;
                                break;
                            }
                        }

                        if (better_found)
                        {
                            break;
                        }
                    }

                    if (!better_found)
                    {
                        break;
                    }
                }
            }
            else // greedy
            {
                // based on http://on-demand.gputechconf.com/gtc/2014/presentations/S4534-high-speed-2-opt-tsp-solver.pdf

                while (true)
                {
                    float min_change = 0;

                    int min_i = -1;
                    int min_j = -1;

                    for (int i = 0; i < best_tour.Count - 2; ++i)
                    {
                        for (int j = i + 2; j < best_tour.Count - 1; ++j)
                        {
                            int city_a = best_tour[i].GlobalId;
                            int city_b = best_tour[i + 1].GlobalId;
                            int city_c = best_tour[j].GlobalId;
                            int city_d = best_tour[j + 1].GlobalId;

                            float change = (distances.GetDistance(city_a, city_c) + distances.GetDistance(city_b, city_d)) -
                                           (distances.GetDistance(city_a, city_b) + distances.GetDistance(city_c, city_d));

                            if (change < min_change)
                            {
                                min_change = change;
                                min_i      = i + 1;
                                min_j      = j;
                            }
                        }
                    }

                    if (min_change >= 0)
                    {
                        break;
                    }

                    // apply min_i/min_j move
                    ExploreCell t = best_tour[min_i];
                    best_tour[min_i] = best_tour[min_j];
                    best_tour[min_j] = t;
                }
            }

            //Navmesh.Log("[FindExplorePath 2-Opt] Final solution distance: " + GetTravelDistance(tour, distances));

            foreach (ExploreCell cell in best_tour)
            {
                path.Add(cell.Position);
            }

            if (start_cell.Explored)
            {
                path.RemoveAt(0);
            }
        }
Пример #30
0
        public static void FindExplorePath(ExploreCell start_cell, List <ExploreCell> explore_cells, CellsDistancer distances, ref List <Vec3> path)
        {
            //based on http://www.theprojectspot.com/tutorial-post/simulated-annealing-algorithm-for-beginners/6

            path.Clear();

            if (start_cell == null)
            {
                return;
            }

            List <int> cells_id_in_start_cell_network = distances.GetConnectedTo(start_cell.GlobalId);

            List <ExploreCell> best_solution = explore_cells.FindAll(c => cells_id_in_start_cell_network.Contains(c.Id));

            best_solution.RemoveAll(c => (c.Explored || c.Neighbours.Count == 0) && c.GlobalId != start_cell.GlobalId);
            best_solution.Remove(start_cell);
            best_solution.Insert(0, start_cell);

            if (best_solution.Count == 1)
            {
                path.Add(best_solution[0].Position);
                return;
            }

            float best_energy = GetTravelDistance(best_solution, distances);

            List <ExploreCell> current_solution = best_solution;
            float current_energy = best_energy;

            Random rng = new Random();

            double temp            = 10000;
            double alpha           = 0.999;
            double epsilon         = 0.0001;
            int    temp_iterations = 2;

            // Loop until system has cooled
            while (temp > epsilon)
            {
                for (int iter = 0; iter < temp_iterations; ++iter)
                {
                    // Create new neighbour tour
                    List <ExploreCell> new_solution = new List <ExploreCell>(current_solution);

                    // Get a random positions in the tour
                    int tour_pos_1 = rng.Next(1, new_solution.Count);
                    int tour_pos_2 = rng.Next(1, new_solution.Count);

                    // Swap them
                    ExploreCell t = new_solution[tour_pos_1];
                    new_solution[tour_pos_1] = new_solution[tour_pos_2];
                    new_solution[tour_pos_2] = t;

                    // Get energy of solutions
                    float new_energy = GetTravelDistance(new_solution, distances);

                    // Decide if we should accept the neighbour
                    if (AcceptanceProbability(current_energy, new_energy, temp) >= rng.NextDouble())
                    {
                        current_solution = new_solution;
                        current_energy   = new_energy;
                    }

                    // Keep track of the best solution found
                    if (current_energy < best_energy)
                    {
                        best_solution = current_solution;
                        best_energy   = current_energy;
                    }
                }

                // Cool system
                temp *= alpha;
            }

            //Navmesh.Log("[FindExplorePath] Final solution distance: " + best_energy);

            foreach (ExploreCell cell in best_solution)
            {
                path.Add(cell.Position);
            }

            if (start_cell.Explored)
            {
                path.RemoveAt(0);
            }
        }
Пример #31
0
        internal virtual void Deserialize(List<Cell> all_cells, BinaryReader r)
        {
            using (new WriteLock(DataLock))
            using (new WriteLock(InputLock))
            {
                m_ExploreCells.Clear();
                m_ExploreCellsDistancer.Clear();

                m_Enabled = r.ReadBoolean();

                int explore_cells_count = r.ReadInt32();

                // pre-allocate explore cells
                for (int i = 0; i < explore_cells_count; ++i)
                {
                    ExploreCell explore_cell = new ExploreCell();
                    explore_cell.GlobalId = r.ReadInt32();
                    m_ExploreCells.Add(explore_cell);
                }

                m_ExploreCells.Sort(new Cell.CompareByGlobalId());

                foreach (ExploreCell explore_cell in m_ExploreCells)
                    explore_cell.Deserialize(m_ExploreCells, all_cells, r);

                ExploreCell.LastExploreCellGlobalId = r.ReadInt32();

                m_ExploreCellsDistancer.Deserialize(r);

                m_HintPos = new Vec3(r);
            }
        }
Пример #32
0
        private int GenerateExploreCells(AABB cell_aabb)
        {
            // should not happen
            //if (m_ExploreCells.Exists(x => x.AABB.Equals(cell_aabb)))
            //    return;

            MovementFlag movement_flags = Navmesh.Navigator.MovementFlags;

            //using (new Profiler("[Nav] Nav data generated [{t}]"))
            using (Navmesh.AquireReadDataLock())
            {
                List<Cell> cells = new List<Cell>();

                // find all cells inside cell_aabb
                foreach (GridCell grid_cell in Navmesh.m_GridCells)
                {
                    if (!cell_aabb.Overlaps2D(grid_cell.AABB))
                        continue;

                    cells.AddRange(grid_cell.Cells.FindAll(x => !x.Replacement && x.HasFlags(movement_flags) && cell_aabb.Overlaps2D(x.AABB)));
                }

                // add all replaced cells overlapped by explore cell
                //cells.AddRange(Navmesh.GetReplacedCells().FindAll(x => x.HasFlags(movement_flags) && cell_aabb.Overlaps2D(x.AABB)));

                //create ExploreCell for each interconnected group of cells
                List<Cell> cells_copy = new List<Cell>(cells);
                int last_explore_cells_count = m_ExploreCells.Count;

                while (cells_copy.Count > 0)
                {
                    List<Cell> visited = new List<Cell>();

                    Algorihms.Visit(cells_copy[0], ref visited, movement_flags, true, 1, -1, cells_copy);

                    List<AABB> intersections = new List<AABB>();
                    AABB intersections_aabb = new AABB();

                    foreach (Cell c in visited)
                    {
                        AABB intersection = cell_aabb.Intersect(c.AABB);

                        intersections.Add(intersection);
                        intersections_aabb.Extend(intersection);
                    }

                    Vec3 nearest_intersection_center = Vec3.Empty;
                    float nearest_intersection_dist = float.MaxValue;

                    foreach (AABB inter_aabb in intersections)
                    {
                        float dist = inter_aabb.Center.Distance2D(intersections_aabb.Center);

                        if (dist < nearest_intersection_dist)
                        {
                            nearest_intersection_center = inter_aabb.Center;
                            nearest_intersection_dist = dist;
                        }
                    }

                    ExploreCell ex_cell = new ExploreCell(cell_aabb, visited, nearest_intersection_center, m_LastExploreCellId++);
                    Add(ex_cell);

                    ex_cell.Small = (ex_cell.CellsArea() < MAX_AREA_TO_MARK_AS_SMALL);

                    cells_copy.RemoveAll(x => visited.Contains(x));
                }

                return m_ExploreCells.Count - last_explore_cells_count;
            }
        }
Пример #33
0
        private void Add(ExploreCell explore_cell)
        {
            using (new WriteLock(DataLock))
            {
                foreach (ExploreCell e_cell in m_ExploreCells)
                {
                    if (e_cell.AddNeighbour(explore_cell))
                        m_ExploreCellsDistancer.Connect(e_cell.GlobalId, explore_cell.GlobalId, e_cell.Position.Distance2D(explore_cell.Position));
                }

                m_ExploreCells.Add(explore_cell);
            }
        }
Пример #34
0
        protected List<int> GetUnexploredCellsId(ExploreCell origin_cell)
        {
            using (new ReadLock(DataLock))
            {
                List<ExploreCell> unexplored_cells = m_ExploreCells.FindAll(x => !x.Explored);
                List<ExploreCell> big_unexplored_cells = unexplored_cells.FindAll(x => !x.Small);

                List<int> unexplored_cells_id = null;

                // explore small cells only when all other cells were explored
                if (big_unexplored_cells.Count == 0)
                    unexplored_cells_id = unexplored_cells.Select(x => x.GlobalId).ToList();
                else
                    unexplored_cells_id = big_unexplored_cells.Select(x => x.GlobalId).ToList();

                List<int> potential_cells_id = m_ExploreCellsDistancer.GetConnectedTo(origin_cell.GlobalId);

                return potential_cells_id.Intersect(unexplored_cells_id).ToList(); // consider only unexplored
            }
        }
Пример #35
0
 protected virtual void OnCellExplored(ExploreCell cell)
 {
     cell.Explored = true; // this is safe as explore cells cannot be added/removed now
     Navmesh.Log("[Nav] Explored cell " + cell.GlobalId + " [progress: " + GetExploredPercent() + "%]!");
 }
Пример #36
0
        // assume Navmesh data lock is aquired
        private int GenerateExploreCells(AABB cell_aabb)
        {
            // should not happen
            //if (m_ExploreCells.Exists(x => x.AABB.Equals(cell_aabb)))
            //    return;

            MovementFlag movement_flags = m_Navigator.MovementFlags;

            //using (new Profiler("[Nav] Nav data generated [%t]"))
            //using (m_Navmesh.AquireReadDataLock())
            {
                List <Cell> cells = new List <Cell>();

                // i'm interested in unique list
                HashSet <int> tmp_overlapping_grid_cells = new HashSet <int>();

                // find all cells inside cell_aabb
                using (m_Navmesh.AcquireReadDataLock())
                {
                    foreach (GridCell grid_cell in m_Navmesh.m_GridCells.Where(x => x.AABB.Overlaps2D(cell_aabb)))
                    {
                        tmp_overlapping_grid_cells.Add(grid_cell.Id);

                        cells.AddRange(grid_cell.GetCells(x => x.HasFlags(movement_flags) && cell_aabb.Overlaps2D(x.AABB), false));
                    }
                }

                // for traversing purposes list will be faster
                List <int> overlapping_grid_cells = tmp_overlapping_grid_cells.ToList();

                //create ExploreCell for each interconnected group of cells
                HashSet <Cell> cells_copy = new HashSet <Cell>(cells);
                int            last_explore_cells_count = m_ExploreCells.Count;

                while (cells_copy.Count > 0)
                {
                    HashSet <Cell> visited = new HashSet <Cell>();

                    using (m_Navmesh.AcquireReadDataLock())
                        Algorihms.Visit(cells_copy.First(), ref visited, movement_flags, true, 1, -1, cells_copy);

                    List <AABB> intersections      = new List <AABB>();
                    AABB        intersections_aabb = new AABB();

                    AABB intersection = default(AABB);

                    foreach (Cell c in visited)
                    {
                        if (cell_aabb.Intersect(c.AABB, ref intersection))
                        {
                            intersections.Add(intersection);
                            intersections_aabb = intersections_aabb.Extend(intersection);
                        }
                    }

                    ExploreCell ex_cell = new ExploreCell(cell_aabb, visited.ToList(), overlapping_grid_cells, m_LastExploreCellId++);
                    Add(ex_cell);

                    ex_cell.Small = (ex_cell.CellsArea < MaxAreaToMarkAsSmall) || (ex_cell.CellsAABB.Dimensions.Max() < MaxDimensionToMarkAsSmall);

                    cells_copy.RemoveWhere(x => visited.Contains(x));
                }

                return(m_ExploreCells.Count - last_explore_cells_count);
            }
        }
Пример #37
0
 public float ExploreDistance(ExploreCell cell_1, ExploreCell cell_2)
 {
     using (new ReadLock(DataLock))
         return m_ExploreCellsDistancer.GetDistance(cell_1.GlobalId, cell_2.GlobalId);
 }