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); }
/// <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; }
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); }
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); }
/// <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(); }
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); }
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); }
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); }
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; //} }