3

I have a project that I need to make an image follow a spline.

I build the spline using Graphics.DrawCurve through an array of Points.

I'm trying to use PointAnimationUsingPath but I can't seem to get it to work. Apparently it doesn't work in C# with Windows form.

Can someone give me a light on how to do this?

Thank you All.

-----EDIT----- enter image description here Change to a WPF UserControl as recommend in comments.

Still need some help as the shape does not move exactly following the dots, below my code:

 public partial class SplineBox : UserControl
{
    Point[] finalPoint;

    public SplineBox()
    {
        InitializeComponent();

    }

    public void MoveShape(Point[] _path)
    {
        // Create a NameScope for the page so that
        // we can use Storyboards.
        NameScope.SetNameScope(this, new NameScope());

        // Create the EllipseGeometry to animate.
        EllipseGeometry animatedEllipseGeometry =
            new EllipseGeometry(new Point(10, 100), 15, 15);

        // Register the EllipseGeometry's name with
        // the page so that it can be targeted by a
        // storyboard.
        this.RegisterName("AnimatedEllipseGeometry", animatedEllipseGeometry);

        // Create a Path element to display the geometry.
        Path ellipsePath = new Path();
        ellipsePath.Data = animatedEllipseGeometry;
        ellipsePath.Fill = Brushes.Blue;
        ellipsePath.Margin = new Thickness(15);

        SplineCanvas.Children.Add(ellipsePath);
        this.Content = SplineCanvas;

        // Create the animation path.
        PathGeometry animationPath = new PathGeometry();
        PathFigure pFigure = new PathFigure();
        pFigure.StartPoint = _path[0];

        PolyBezierSegment pBezierSegment = new PolyBezierSegment();

        for (int p = 1; p < _path.Length; p++)
        {
            pBezierSegment.Points.Add(_path[p]);
        }

        pFigure.Segments.Add(pBezierSegment);
        animationPath.Figures.Add(pFigure);

        // Freeze the PathGeometry for performance benefits.
        animationPath.Freeze();

        // Create a PointAnimationgUsingPath to move
        // the EllipseGeometry along the animation path.
        PointAnimationUsingPath centerPointAnimation =  new PointAnimationUsingPath();
        centerPointAnimation.PathGeometry = animationPath;
        centerPointAnimation.Duration = TimeSpan.FromSeconds(5);
        centerPointAnimation.RepeatBehavior = RepeatBehavior.Forever;

        // Set the animation to target the Center property
        // of the EllipseGeometry named "AnimatedEllipseGeometry".
        Storyboard.SetTargetName(centerPointAnimation, "AnimatedEllipseGeometry");
        Storyboard.SetTargetProperty(centerPointAnimation,
            new PropertyPath(EllipseGeometry.CenterProperty));

        // Create a Storyboard to contain and apply the animation.
        Storyboard pathAnimationStoryboard = new Storyboard();
        pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
        pathAnimationStoryboard.AutoReverse = true;
        pathAnimationStoryboard.Children.Add(centerPointAnimation);

        // Start the Storyboard when ellipsePath is loaded.
        ellipsePath.Loaded += delegate (object sender, RoutedEventArgs e)
        {
            // Start the storyboard.
            pathAnimationStoryboard.Begin(this);
        };
    }

    public void Paint(ScreenObject _spline)
    {            

        List<Point> points = new List<Point>();

        if (true)
        {
            var spline = _spline;

            foreach (System.Windows.Point point in spline.SplineAnchors)
            {
                Point tempP = new Point((int)point.X, (int)point.Y);
                points.Add(tempP);
            }


            finalPoint = points.ToArray();

            //Pen pen = new Pen(Color.FromArgb(255, 0, 0, 255), 1);
            //e.Graphics.DrawCurve(pen, finalPoint);

            foreach (Point p in finalPoint)
            {
                // Create a red Ellipse.
                Ellipse myEllipse = new Ellipse();

                // Create a SolidColorBrush with a red color to fill the
                // Ellipse with.
                SolidColorBrush mySolidColorBrush = new SolidColorBrush();

                // Describes the brush's color using RGB values.
                // Each value has a range of 0-255.
                mySolidColorBrush.Color = Color.FromArgb(255, 100, 255, 0);
                myEllipse.Fill = mySolidColorBrush;
                myEllipse.StrokeThickness = 2;
                myEllipse.Stroke = Brushes.Black;

                // Set the width and height of the Ellipse.
                myEllipse.Width = 10;
                myEllipse.Height = 10;

                myEllipse.Margin = new Thickness(p.X - 5, p.Y - 5, 0, 0);
                //e.Graphics.DrawRectangle(pen, new Rectangle(p.X - 5, p.Y - 5, 10, 10));
                //e.Graphics.FillRectangle(Brushes.Red, new Rectangle(p.X - 5, p.Y - 5, 10, 10));

                SplineCanvas.Children.Add(myEllipse);
            }
        }
    }

}
Xibira
  • 43
  • 3
  • When you say follow, you mean you need to create an animation? – Trevor Elliott May 19 '20 at 10:54
  • @TrevorElliott yes, the image or rectangle need to move following the DrawCurve line – Xibira May 19 '20 at 10:58
  • A Bezier curve created by the GraphicsPath class exposes all the points that define the curve. Custom markers can be defined. You can use these points to move a shape, using the Points as reference position (*reference* because the GraphicsPath is not a PathGeometry and you have to calculate the variances on your own). – Jimi May 19 '20 at 11:04
  • The point data of the path won't let you animate properly. You need to be able to track the elapsed time and calculate the percentage of the animation to be rendered, then feed that percentage into a method which will output the point. See this question for a reference (https://stackoverflow.com/questions/40471362/compute-points-from-bezier-path). Unless you are already comfortable doing so, you will also need to learn how to render animations in WinForms using a timer. – Trevor Elliott May 19 '20 at 11:19
  • This can be solved much more easily using WPF instead of WinForms, if that's an option. – Trevor Elliott May 19 '20 at 11:20
  • @TrevorElliott unfortunately not, it's an old project and i'm implementing some new things. – Xibira May 19 '20 at 11:30
  • I tried to use this method: https://learn.microsoft.com/en-us/dotnet/framework/wpf/graphics-multimedia/how-to-animate-the-position-of-an-object-by-using- pointanimation But it is for WPF and I was not successful converting to winform – Xibira May 19 '20 at 11:39
  • @TrevorElliott Is it possible to use a WPF window within a winform project? I noticed that I can insert a UserControl (WPF) but I have no experience with WPF – Xibira May 19 '20 at 11:54
  • @TrevorElliott ok, i´m using a WPF userControl, but the shape almost(XD) follow the points...but there is a small difference in the route.. i will post my code so maybe you can help me. – Xibira May 19 '20 at 14:33

0 Answers0