예제 #1
0
        private void DoFind()
        {
            _result = new PhoneNumberService().FindAllPhoneNumbers(SelectedPiece.Piece);
            NumberOfPhoneNumbers = _result.AllPaths.Count;
            Trees = (from t in _result.PathTrees select new TreeNodeViewModel(t.Root));
            List<string> phoneNumbers = new List<string>();

            foreach (Path p in _result.AllPaths)
            {
                StringBuilder phoneNumber = new StringBuilder();
                int count = 1;
                foreach (Key k in p.Keys)
                {
                    phoneNumber.Append(k.Digit);
                    count++;

                    if(count == 4)
                    {
                        phoneNumber.Append("-");
                    }
                }
                phoneNumbers.Add(phoneNumber.ToString());
            }

            phoneNumbers.Sort();
            PhoneNumbers = phoneNumbers;

            if (SelectedPiece.IsLongRunning)
            {
                ShowFindingProgressIndicator = false;
                ShowResults = true;
            }
        }
        public PathFinderResult GetResultById(int id)
        {
            PathFinderResult result = null;

            try
            {
                var command = _sqliteConnection.CreateCommand();
                command.CommandText = @"
                SELECT *
                FROM ProcessedPath
                WHERE Id = @id";
                command.Parameters.AddWithValue("@id", id);

                var reader = command.ExecuteReader();
                while (reader.Read())
                {
                    result = MapDbToModel(reader);
                }
            }
            catch
            {
                //Ignore for now. TODO logging.
            }

            return(result);
        }
예제 #3
0
        /// <summary>
        ///  让采集车移动到有经纬度确定的地点
        ///  Ask the harvester to move to a given location, which is represented
        ///  by longtitude and latitude
        /// </summary>
        /// <param name="lng"></param>
        /// <param name="lat"></param>
        public void Move(float lng, float lat)
        {
            //IsAuto = false;
            movePurpose = MovePurpose.None;

            int sx, sy;

            Map.GetMapCoord(longtitude, latitude, out sx, out sy);

            int tx, ty;

            Map.GetMapCoord(lng, lat, out tx, out ty);

            destX = tx;
            destY = ty;

            finder.Reset();
            currentPath = finder.FindPath(sx, sy, tx, ty);

            // 新的动作要先调整朝向
            // Adjust direction before going
            isAdjustingDirection = true;

            currentNode        = 0;
            nodeMotionProgress = 0;
        }
예제 #4
0
    public PathFinderResult FindPath()
    {
        if (from == null || to == null)
        {
            return(new PathFinderResult());
        }

        //D(map);
        //D("from:", from);
        //D("to:", to);

        var pathItems = new AStar(map, from, to, directionOffest, WeightFunction).Find();

        if (!pathItems.Any())
        {
            D("NO_PATH");
            return(PathFinderResult.NO_PATH);
        }

        var p = new PathFinderResult
        {
            Path           = pathItems.Select(x => x.Pos).ToArray(),
            WeightedLength = pathItems.Last().CumulativeLength
        };

        //D("found path:", p.WeightedLength);

        return(p);
    }
예제 #5
0
        public PathFinderResult <T> FindPath(Vertex <T> source, Vertex <T> destination)
        {
            this.destination = destination;
            var result = new PathFinderResult <T>();

            if (source == null || source.Edges == null || !source.Edges.Any() ||
                destination == null || destination.Edges == null || !destination.Edges.Any())
            {
                result.Success = false;
                return(result);
            }
            var closedset = new List <Vertex <T> >();
            var openset   = source.Edges.Select(edge => edge.B).ToList();

            this.gScore[source] = 0;

            do
            {
                var vertexWithLowestFScore = this.GetVertexWithLowestFScore(openset);
                if (vertexWithLowestFScore == destination)
                {
                    result.Path    = this.ReconstructPath(vertexWithLowestFScore, destination);
                    result.Success = true;
                    return(result);
                }
                openset.Remove(vertexWithLowestFScore);
                closedset.Add(vertexWithLowestFScore);

                foreach (var neightbor in vertexWithLowestFScore.Edges.Select(edge => edge.B).ToList())
                {
                    if (closedset.Contains(neightbor))
                    {
                        continue;
                    }
                    var tentative_g_score   = this.gScore[vertexWithLowestFScore] + DistanceBetween(vertexWithLowestFScore, neightbor);
                    var tentative_is_better = false;

                    if (!openset.Contains(neightbor))
                    {
                        openset.Add(neightbor);
                        this.hScore[neightbor] = this.getHeuristicEstimateOfDistanceToGoalFrom(neightbor, destination);
                        tentative_is_better    = true;
                    }
                    else if (tentative_g_score < this.gScore[neightbor])
                    {
                        tentative_is_better = true;
                    }
                    if (tentative_is_better)
                    {
                        this.cameFrom[neightbor] = vertexWithLowestFScore;
                        this.gScore[neightbor]   = tentative_g_score;
                        this.fScore[neightbor]   = this.gScore[neightbor] + this.hScore[neightbor];
                    }
                }
            } while (openset.Any());

            result.Success = false;
            return(result);
        }
예제 #6
0
        /// <summary>
        ///  当寻路需要RCPF的时候,调用这个继续寻路
        ///  This Move is used when the pathing finding requires continues finding
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        void Move(int x, int y)
        {
            int sx, sy;

            Map.GetMapCoord(longtitude, latitude, out sx, out sy);

            destX = x;
            destY = y;

            finder.Reset();
            currentPath        = finder.FindPath(sx, sy, x, y);
            currentNode        = 0;
            nodeMotionProgress = 0;
        }
        public void AddResult(PathFinderResult model)
        {
            try
            {
                using var transaction = _sqliteConnection.BeginTransaction();
                var insertCmd = _sqliteConnection.CreateCommand();

                SetModelInsertCommand(insertCmd, model);

                transaction.Commit();
            }
            catch
            {
                //Ignore for now. TODO logging.
            }
        }
 private void SetModelInsertCommand(SqliteCommand command, PathFinderResult model)
 {
     command.CommandText = @"
         INSERT OR IGNORE INTO ProcessedPath(Input,IsValid,Result) 
         VALUES(@input, @isValid, @result)";
     command.Parameters.AddWithValue("@input", model.Input);
     command.Parameters.AddWithValue("@isValid", model.HasValidPath);
     if (!string.IsNullOrEmpty(model.MostEfficientPath))
     {
         command.Parameters.AddWithValue("@result", model.MostEfficientPath);
     }
     else
     {
         command.Parameters.AddWithValue("@result", DBNull.Value);
     }
     command.ExecuteNonQuery();
 }
예제 #9
0
        public void TestVerticesCartesianPointScenarios(
            Vertex <Point> source, Vertex <Point> destination, PathFinderResult <Point> exceptedResult)
        {
            // Arrange
            float HeuristicEstimateOfDistanceToGoalAlgorithm(Vertex <Point> current, Vertex <Point> dest)
            {
                double distance = Math.Sqrt(Math.Pow(dest.Position.X - current.Position.X, 2) + Math.Pow(dest.Position.Y - current.Position.Y, 2));

                return((float)distance);
            }

            var pathFinder = new PathFinder <Point>(HeuristicEstimateOfDistanceToGoalAlgorithm);

            // Act
            var result = pathFinder.FindPath(source, destination);

            // Assert
            result.Success.ShouldBe(exceptedResult.Success);
        }
예제 #10
0
        public void TestVerticesLineScenarios(
            Vertex <int> source, Vertex <int> destination, PathFinderResult <int> exceptedResult)
        {
            // Arrange
            float HeuristicEstimateOfDistanceToGoalAlgorithm(Vertex <int> current, Vertex <int> dest)
            {
                float distance = current.Position > dest.Position ? current.Position - dest.Position : dest.Position - dest.Position;

                return(distance < 0 ? -distance : distance);
            }

            var pathFinder = new PathFinder <int>(HeuristicEstimateOfDistanceToGoalAlgorithm);

            // Act
            var result = pathFinder.FindPath(source, destination);

            // Assert
            result.Success.ShouldBe(exceptedResult.Success);
        }
예제 #11
0
        protected override void Draw(GameTime gameTime)
        {
            this.GraphicsDevice.Clear(Color.CornflowerBlue);

            this.networkVisualization.Draw();

            this.gui.BeginLayout(gameTime);

            ImGui.BeginMainMenuBar();
            {
                if (ImGui.BeginMenu("Exit"))
                {
                    this.Exit();
                    ImGui.EndMenu();
                }

                if (ImGui.Begin("Network Overview"))
                {
                    if (ImGui.Button("Generate Grid"))
                    {
                        this.networkVisualization.Clear();
                        this.currentItem = 0;
                        this.GenerateManhattan();
                    }

                    var roads = this.networkVisualization.All();
                    if (ImGui.ListBox("Roads", ref this.currentItem, roads.Select(x => $"{x.Start} -> {x.End}").ToArray(), roads.Count, Math.Min(roads.Count, 15)))
                    {
                        this.networkVisualization.ClearHighLights();
                        this.networkVisualization.Highlight(roads[this.currentItem]);
                    }

                    if (ImGui.Button("Plan Route"))
                    {
                        this.networkVisualization.ClearHighLights();
                        this.pathFinderResult = PathFinder.FindPath(roads[0].StartJunction, roads[this.currentItem].StartJunction);
                        if (this.pathFinderResult.FoundPath)
                        {
                            for (var i = 0; i < this.pathFinderResult.Path.Count; i++)
                            {
                                this.networkVisualization.Highlight(this.pathFinderResult.Path[i]);
                            }
                        }
                    }

                    if (this.pathFinderResult != null && this.pathFinderResult.FoundPath)
                    {
                        ImGui.Text($"Cost: {this.pathFinderResult.Cost}s");
                        ImGui.Text($"Steps: {this.pathFinderResult.Path.Count}");
                        ImGui.Text($"Average Speed: {this.pathFinderResult.Path.Average(x => x.SpeedLimit):F2}Km/h");
                    }

                    ImGui.End();
                }
            }
            ImGui.EndMainMenuBar();
            //ImGui.ShowDemoWindow();

            this.gui.EndLayout();

            base.Draw(gameTime);
        }
예제 #12
0
        public override void Update(GameTime dt)
        {
            float ddt = (float)dt.ElapsedGameTimeSeconds;

            #region 装货卸货
            // Process the loading/unloading
            if (isLoading && exRes != null)
            {
                if (harvStorage < props.Storage)
                {
                    // 计算开矿倍数,保证能够完成卸货
                    // calculate the loading/unloading ratio, to ensure with this speed multiplier
                    // the harvester can finish the job in time.
                    float scale = props.Storage / (RulesTable.HarvLoadingSpeed * RulesTable.HarvLoadingTime);

                    harvStorage += exRes.Exploit(RulesTable.HarvLoadingSpeed * ddt * scale);
                }
                loadingTime -= ddt;

                // 开矿loadingTime时间之后,停止并引发事件
                // when the time runs out, stop to raise the event
                if (loadingTime < 0)
                {
                    isFullLoaded = harvStorage >= props.Storage;
                    isLoading    = false;
                    if (GotThere != null)
                    {
                        GotThere(this, EventArgs.Empty);
                    }
                }
            }

            //else
            //{
            //    isFullLoaded = true;
            //    loadingTime = 0;
            //    if (GotThere != null)
            //        GotThere(this, EventArgs.Empty);
            //}
            if (isUnloading)
            {
                // 计算开矿倍数,保证能够完成卸货
                // calculate the loading/unloading ratio, to ensure with this speed multiplier
                // the harvester can finish the job in time.
                float scale = props.Storage / (RulesTable.HarvLoadingSpeed * RulesTable.HarvLoadingTime);

                float change = RulesTable.HarvLoadingSpeed * ddt * scale;

                // 检查车上的存量是否足够
                // check if remaining storage is enough
                if (harvStorage - change > 0)
                {
                    // 足够时定量卸下
                    // unload all when enough
                    harvStorage -= change;
                    // 并且通知城市得到资源
                    // and tell the city the amount of resource obtained
                    parent.NotifyGotResource(change);
                }
                else
                {
                    // 不够时把剩下的都卸了
                    // otherwise, unload all the remains
                    parent.NotifyGotResource(harvStorage);
                    harvStorage = 0;
                }

                loadingTime -= ddt;

                // 一定时间后停止
                // when the time runs out, stop to raise the event
                if (loadingTime < 0)
                {
                    isUnloading = false;
                    if (GotHome != null)
                    {
                        GotHome(this, EventArgs.Empty);
                    }
                }
            }
            #endregion

            float altitude = map.GetHeight(longtitude, latitude);

            if (currentPath != null)
            {
                int nextNode = currentNode + 1;

                if (nextNode >= currentPath.NodeCount)
                {
                    #region 寻路完毕,状态转换
                    // when the path following is finished, by reaching the final node
                    // switch to new state
                    nextNode           = 0;
                    nodeMotionProgress = 0;

                    if (currentPath.RequiresPathFinding)
                    {
                        // continues path finding
                        Move(destX, destY);
                    }
                    else
                    {
                        // stop by setting null
                        currentPath = null;

                        if (movePurpose == MovePurpose.Gather)
                        {
                            isLoading   = true;
                            loadingTime = RulesTable.HarvLoadingTime;
                        }
                        else if (movePurpose == MovePurpose.Home)
                        {
                            isUnloading = true;
                            loadingTime = RulesTable.HarvLoadingTime;
                        }
                    }
                    #endregion
                }
                else
                {
                    #region 路径节点插值
                    // calculate the interpolation between 2 nodes


                    // 采集车在每两个节点之间移动都是一定过程
                    // 其位置/朝向是插值结果。差值参数为nodeMotionProgress
                    // The locomotion of harvester between 2 MoveNode is a process in time.
                    // Its position and orientation is the result of interpolation, where
                    // nodeMotionProgress is the interpolation amount.

                    Point cp = currentPath[currentNode];
                    Point np = currentPath[nextNode];

                    // 在一开始就尝试获取下一节点位置
                    // Check if the position in the next 2 MoveNodes need to be updated,
                    // as parameters to calculate translation
                    if (!stateUpdated)
                    {
                        if (isAdjustingDirection)
                        {
                            // 在调整方向时,车是位置不动的
                            // The car does not move when changing direction

                            Map.GetCoord(np.X, np.Y, out src.Longitude, out src.Latitude);

                            src.Alt = map.GetHeight(src.Longitude, src.Latitude);

                            target.Longitude = src.Longitude;
                            target.Latitude  = src.Latitude;
                            target.Alt       = src.Alt;
                        }
                        else
                        {
                            Map.GetCoord(cp.X, cp.Y, out src.Longitude, out src.Latitude);
                            Map.GetCoord(np.X, np.Y, out target.Longitude, out target.Latitude);

                            src.Alt    = map.GetHeight(src.Longitude, src.Latitude);
                            target.Alt = map.GetHeight(target.Longitude, target.Latitude);
                        }
                        stateUpdated = true;
                    }

                    // 在进行了一半之后开始获取下一节点朝向
                    // When the interpolation amount run over 0.5, update the
                    // information for orientation of the next 2 nodes, as parameters to calculate
                    // turning.
                    if (nodeMotionProgress > 0.5f && !rotUpdated)
                    {
                        if (isAdjustingDirection)
                        {
                            target.Ori = GetOrientation(cp, np);
                        }
                        else
                        {
                            if (nextNode < currentPath.NodeCount - 1)
                            {
                                src.Ori    = GetOrientation(cp, np);
                                target.Ori = GetOrientation(np, currentPath[nextNode + 1]);
                            }
                            else
                            {
                                target.Ori = GetOrientation(cp, np);
                                src.Ori    = target.Ori;
                            }
                        }
                        rotUpdated = true;
                    }

                    if (!isAdjustingDirection)
                    {
                        float x = MathEx.LinearInterpose(cp.X, np.X, nodeMotionProgress);
                        float y = MathEx.LinearInterpose(cp.Y, np.Y, nodeMotionProgress);

                        Map.GetCoord(x, y, out longtitude, out latitude);
                    }
                    altitude = MathEx.LinearInterpose(src.Alt, target.Alt, nodeMotionProgress);

                    #region 动画控制
                    // Animate by changing the index

                    // Car have a different look when on water
                    if (altitude < 0)
                    {
                        mdlIndex++;
                    }
                    else
                    {
                        mdlIndex--;
                    }

                    if (mdlIndex < 0)
                    {
                        mdlIndex = 0;
                    }
                    if (mdlIndex >= NumModels)
                    {
                        mdlIndex = NumModels - 1;
                    }

                    if (model != null)
                    {
                        if (parent.Owner != null)
                        {
                            if (parent.Type == CityType.Oil)
                            {
                                ModelL0 = model_bad[mdlIndex];
                            }
                            else
                            {
                                ModelL0 = model[mdlIndex];
                            }
                        }
                        else
                        {
                            ModelL0 = null;
                        }
                    }
                    #endregion

                    // 采集车不会潜水
                    // Keep the car not diving
                    if (altitude < 0)
                    {
                        altitude = 0;
                    }

                    // 球面插值,计算出朝向
                    // Spherical interpolation for direction
                    Orientation = Matrix.RotationQuaternion(
                        Quaternion.Slerp(src.Ori, target.Ori, nodeMotionProgress > 0.5f ? nodeMotionProgress - 0.5f : nodeMotionProgress + 0.5f));

                    if (isAdjustingDirection)
                    {
                        nodeMotionProgress += 0.5f * ddt;
                    }
                    else
                    {
                        // 挺进节点插值进度
                        // Progress the interpolation between 2 nodes
                        nodeMotionProgress += 0.05f * acceleration;
                    }

                    // 检查节点之间插值是否完成
                    // Check if the interpolation is done
                    if (nodeMotionProgress > 1)
                    {
                        nodeMotionProgress = 0;

                        if (isAdjustingDirection)
                        {
                            // 我们只允许调整方向一次,调整这次不会让车在节点上移动,currentNode不变
                            // We only allow adjust the direction once
                            isAdjustingDirection = false;
                        }
                        else
                        {
                            currentNode++;
                        }

                        rotUpdated   = false;
                        stateUpdated = false;
                    }
                    #endregion
                }

                #region 加速度计算
                // Calculate the acceleration
                if (currentPath != null)
                {
                    // 检查是否是最后一个节点了
                    // Check if this is the last node
                    if (nextNode == currentPath.NodeCount - 1)
                    {
                        // 开始减速
                        // Deceleration
                        acceleration -= ddt * 1.5f;
                        // 防止减速的过慢
                        // Set the minimum
                        if (acceleration < 0.33f)
                        {
                            acceleration = 0.33f;
                        }
                    }
                    else if (!isAdjustingDirection)
                    {
                        // 平时都是加速到最大为止
                        // otherwise, increase to full speed
                        acceleration += ddt * 1.5f;
                        if (acceleration > 1)
                        {
                            acceleration = 1;
                        }
                    }
                }
                #endregion
            }
            else
            {
                acceleration = 0;
            }


            //Orientation *= PlanetEarth.GetOrientation(longtitude, latitude);

            // 通过插值计算的经纬度得到坐标
            // The position is obtained by the interpolated long-lat coordinate
            Position = PlanetEarth.GetPosition(longtitude, latitude, PlanetEarth.PlanetRadius + altitude);
            base.Update(dt);



            BattleField field = map.Field;


            if (parent != null && parent.Owner != null && parent.Owner.Type == PlayerType.LocalHuman)
            {
                field.Fog.LightArea(longtitude,
                                    latitude, MathEx.Degree2Radian(5));
            }

            Visibility = field.Fog.GetVisibility(longtitude,
                                                 latitude);
            //if (IsSelected && IsInVisibleRange)
            //{
            //    IsSelected = false;

            //}
        }