Search code examples
c#.netwinformssavepoints

Write points drawn over a chart control to a text file the but only once each coordinate?


In a button click event:

private void chart1_MouseClick(object sender, MouseEventArgs e)
{
    if (outofrange == false)
    {
        valuePoints.Add(new PointF(X, Y));
        paintToCalaculate = true;

        if (X > 0 && Y > 0)
        {
            chart1.Invalidate();
            SavePointsCoordinates();
        }
    }
}

And the SavePointsCoordinates method:

StreamWriter w;
int countPoints = 0;

private void SavePointsCoordinates()
{
    if (drawPoints.Count > 0)
    {
        foreach (Point p in drawPoints)
        {
            countPoints++;
            w = new StreamWriter(@"c:\chart\chartData.txt",true);
            w.WriteLine("Point " + countPoints + "X = " + p.X + " Y = " + p.Y);
        }

        w.Close();
    }
}

The problem is that if I will click the button more then once without adding new points it will keep adding to the text file the same coordinates.

In fact it's adding the same point coordinates already to the valuePoints in the button click event. valuePoints is List

And drawPoints is List I'm using in the chart1 paint event:

Pen pen = new Pen(Color.Blue, 2.5f);
SolidBrush myBrush = new SolidBrush(Color.Red);

private void chart1_Paint(object sender, PaintEventArgs e)
{
    if (paintToCalaculate)
    {
        Series s = chart1.Series.FindByName("dummy");

        if (s == null)
        {
            s = chart1.Series.Add("dummy");
        }

        drawPoints.Clear();
        s.Points.Clear();

        foreach (PointF p in valuePoints)
        {
            s.Points.AddXY(p.X, p.Y);
            DataPoint pt = s.Points[0];
            double x = chart1.ChartAreas[0].AxisX.ValueToPixelPosition(pt.XValue);
            double y = chart1.ChartAreas[0].AxisY.ValueToPixelPosition(pt.YValues[0]);
            drawPoints.Add(new Point((int)x, (int)y));
            s.Points.Clear();
        }

        paintToCalaculate = false;
        chart1.Series.Remove(s);
    }

    foreach (Point p in drawPoints)
    {
        e.Graphics.FillEllipse(Brushes.Red, p.X - 2, p.Y - 2, 4, 4);
    }

    if (drawPoints.Count > 1)
    {
        e.Graphics.DrawLines(pen, drawPoints.ToArray());
    }
}

What I want to do is to write all the points coordinates I draw on the chart to a text file and then in the constructor to read back the text file draw the points back to the chart and also to draw the lines between them.

I'm not sure if there is a meaning to the order of the points and lines between them I draw. Just to write all coordinates to the text file and read back.


Solution

  • Here is the recommended way to save a List<Point>. Point is Serializeable, so these few lines will do to save and load a List<Point> points:

    string yourPointsFile = "d:\\myPoints.xml";
    XmlSerializer xmls = new XmlSerializer(typeof(List<Point>));
    
    // save the points maybe when closing the program:
    using (Stream writer = new FileStream(yourPointsFile, FileMode.Create))
    {
        xmls.Serialize(writer, points);
        writer.Close();
    }
    
    // load the points at startup:
    
    using (Stream reader = new FileStream(yourPointsFile, FileMode.Open))
    {
        points = xmls.Deserialize(reader);
        reader.Close();
    }
    

    Collecting the right Points, adding or not adding them is another question. To avoid duplicates you can always use

    if (!points.Contains(somePoint) ) points.Add(somePoint);
    

    The saved and loaded points list will have the same order. So if they are to be used to draw lines, where the order indeed matters, the resulting lines should be the same.

    I don't think saving the points on every click makes sense, but this your program. Maybe it is enough to save them upon closing the program..?

    If, as you do, you instead want to save PointF, simply change both references to Point to PointF.