using RoboforkApp.DataModel; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace RoboforkApp { public class ScheduleCanvas : Canvas { private double COOR_Y = 65; const double RADIUS_NODE = 25; public simulationRobo simulation; private VehicleModelList vehicleModelList; private Point _startPoint; private Point _endPoint; private bool _isGoal = false; private double _speed; private int _index; private List _lstNode; /// /// Create simulation /// /// List node on schedule /// Vehicle model on map /// Current index of vehicle public void CreateSimulation(List lstNode, VehicleModel vehicleModel, int vehicleIndex) { //If node is less than 2 so return if (this.Children.Count < 2) { return; } this.Children.Remove(simulation); this.COOR_Y = DesignerCanvas.CanvasScheduleHeight / 2 - 15; //Init data this._lstNode = lstNode; this.vehicleModelList = vehicleModel.VehicleModelList[vehicleIndex]; this._startPoint = new Point(Canvas.GetLeft(_lstNode[_index]) + RADIUS_NODE, COOR_Y); this._endPoint = new Point(Canvas.GetLeft(_lstNode[_index + 1]) + RADIUS_NODE, COOR_Y); //Get speed double scheDis = GetDistance(_startPoint, _endPoint); double mapDis = GetDistance(new Point(vehicleModelList.pointMapList[_index].pointMap_X, vehicleModelList.pointMapList[_index].pointMap_Y), new Point(vehicleModelList.pointMapList[_index + 1].pointMap_X, vehicleModelList.pointMapList[_index + 1].pointMap_Y + 1)); this._speed = GetSpeed(mapDis, scheDis, vehicleModelList.pointMapList[_index].speed_Map); //Check next node is goal this._index += 1; if (_index == _lstNode.Count - 1) { _isGoal = true; } // Start simulation RoboSimulation(); } /// /// Create robo simulation on line /// private void RoboSimulation() { simulation = new simulationRobo(); simulation.storyBoard = CreatPathAnimation(_startPoint, _endPoint, _speed); this.Children.Add(simulation); } /// /// Get storyboard /// /// Point start line /// Point end line /// speed on line /// Storyboard private Storyboard CreatPathAnimation(Point startPoint, Point endPoit, double speed) { PathGeometry animationPath = new PathGeometry(); PathFigure pFigure = new PathFigure(); pFigure.StartPoint = startPoint; //new Point(50, 65); LineSegment lineSegment = new LineSegment(); lineSegment.Point = endPoit; // new Point(800, 65); pFigure.Segments.Add(lineSegment); animationPath.Figures.Add(pFigure); // Freeze the PathGeometry for performance benefits. animationPath.Freeze(); // Create a MatrixAnimationUsingPath to move the // simulation along the path by animating // its MatrixTransform. MatrixAnimationUsingPath matrixAnimation = new MatrixAnimationUsingPath(); matrixAnimation.PathGeometry = animationPath; matrixAnimation.SpeedRatio = speed; matrixAnimation.AutoReverse = false; matrixAnimation.DoesRotateWithTangent = true; matrixAnimation.Completed += delegate { AnimationCompleted(this._isGoal); }; // Set the animation to target the Matrix property // of the MatrixTransform named "ButtonMatrixTransform". Storyboard.SetTargetName(matrixAnimation, "fl"); Storyboard.SetTargetProperty(matrixAnimation, new PropertyPath(MatrixTransform.MatrixProperty)); // Create a Storyboard to contain and apply the animation. Storyboard pathAnimationStoryboard = new Storyboard(); pathAnimationStoryboard.Children.Add(matrixAnimation); return pathAnimationStoryboard; } /// /// Process when simulation is end line /// /// check is node end private void AnimationCompleted(bool isGoal) { // If not end node if (!isGoal) { this.Children.Remove(simulation); this._startPoint = _endPoint; this._endPoint = new Point(Canvas.GetLeft(_lstNode[_index + 1]) + RADIUS_NODE, COOR_Y); //Get speed double scheDis = GetDistance(_startPoint, _endPoint); double mapDis = GetDistance(new Point(vehicleModelList.pointMapList[_index].pointMap_X, vehicleModelList.pointMapList[_index].pointMap_Y), new Point(vehicleModelList.pointMapList[_index + 1].pointMap_X, vehicleModelList.pointMapList[_index + 1].pointMap_Y + 1)); this._speed = GetSpeed(mapDis, scheDis, vehicleModelList.pointMapList[_index].speed_Map); //Check next node is goal this._index += 1; if (this._index == this._lstNode.Count - 1) { this._isGoal = true; } RoboSimulation(); return; } // Reset data when finish this._index = 0; this._speed = 0; this._isGoal = false; } /// /// Get speed on schedule /// /// Distance the line on Map /// Distance the line on Schedule /// Speed the fork on Map /// Speed the fork on schedule private double GetSpeed(double mapDis, double scheDis, double mapSpeed) { if (mapDis == 0) return 0.0; return mapSpeed * (scheDis / mapDis); } /// /// Get distance between two point /// /// Point 1 /// Point 2 /// Distance between two point private double GetDistance(Point point1, Point point2) { //pythagorean theorem c^2 = a^2 + b^2 //thus c = square root(a^2 + b^2) double a = (double)(point2.X - point1.X); double b = (double)(point2.Y - point1.Y); return Math.Sqrt(a * a + b * b); } } }