views:

411

answers:

2

I have a graphic made dynamically with a polyline object. It produces something interesting but I would like to keep only the last 10 coordonates and once we have reach the 10th position, every coordinate would move to the left by X pixel and the new value will be added at the end.

In the Add function of my drawing class I tried this kind of code:

        if (points.Count > 10)
        {
            myPolyline.Points.RemoveAt(0);

            foreach(Point p in myPolyline.Points)
            {
                p.X = p.X - 50;//Move all coord back to have a place for the new one
            }   
        }

That doesn't work because we cannot modify a variable of the collection in a ForEach loop. What is the best way to do this in WPF/C#?

More info

I can do it by doing this:

            for (int i = 0; i < this.myPolyline.Points.Count; i++)
            {
                this.myPolyline.Points[i] = new Point(this.myPolyline.Points[i].X - 50, this.myPolyline.Points[i].Y);
            }

But I would like a cleaner way to do it without having to create point object very time.

+2  A: 

Well, the Point is a struct, so the overhead of creating new ones shouldn't be bad. Doing the following...

Point p = this.myPolyline.Points[i];
p.X -= 50;
this.myPolyline.Points[i] = p;

...would really be no different, simply because structs are passed around by value.

You are pretty much stuck with a for loop and reassigning to myPolyline.Points[i], considering the circumstances:

  1. You have to modify the Point with a different X value.
  2. You can't modify the variable of a foreach loop, so you have to use a for loop.
  3. myPolyline.Points[i].X -= 50 won't work because of the way the Point struct is retrieved from the array and then not re-assigned automatically.

If you simply wanted to move the whole PolyLine, I might have suggested a LayoutTransform or RenderTransform, but you're moving a subset of Points and then will add others.

Edit: If you really want to refactor that operation, you could create an extension method on PointCollection for the for loop and point tweaking like this:

static public void ChangePoints( this PointCollection pc, Vector v ) {
    for (int i = 0; i < pc.Count; i++ ) {
        pc[i] += v;
        // the above works on the indexer because you're doing an operation on the
        // Point rather than on one of the Point's members.
    }
}

Usage:

myPolyline.Points.ChangePoints( new Vector( -50, 0 ) );

You still have to change the Points in the same way, but it's refactored elsewhere so that the usage is more readable. And usage of Vector makes it more readable, too.

Joel B Fant
+1 and answer accepted. Very complete answer. Thank you for sharing your knowledge.
Daok
You're welcome. To be honest, I didn't know about `Vector` until I was looking at the members of `PointCollection` and `Point` and saw that the latter had operator overloads.
Joel B Fant
+2  A: 

Move the entire canvas left instead and increase the insertionpoint for the new points all the time.

If you have tons of items this will also improve the rendering performance (especially if you animate the movement).