Search code examples
c#chartsmschart

Polar Plot with mschart C#


I'm currently working on a project, in which I need to create a Polar Plot with dynamically generated data. I've managed to create a somewhat decent polar plot, but have not been able to create what is needed. This is my Polar Plot

this is the code I used to set the offset in the middle:

    public Form1()
    {
        InitializeComponent();
        chart1.ChartAreas[0].AxisX.MajorTickMark.Enabled = false;
        chart1.ChartAreas[0].AxisX.MajorGrid.Enabled = false;


        chart1.ChartAreas[0].AxisY.Minimum = -20;
        chart1.ChartAreas[0].AxisY.MajorGrid.IntervalOffset = 15;
        chart1.ChartAreas[0].AxisY.MajorGrid.Interval = 5;
        chart1.ChartAreas[0].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Solid;
        chart1.ChartAreas[0].AxisX.MajorGrid.LineDashStyle = ChartDashStyle.Solid;

    }

I found some help here: How to displace the origin of the Y axis on a polar Mschart?

I got a example on how I'm trying to get the polar: The finished example


Solution

  • I don't think you can make an axis start from anywhere but its minimum.

    (The linked post only makes the labels start from a different value.)

    So we'll have to help with a little bit of owner-drawing.

    A few short references:

    var ca = chart1.ChartAreas[0];
    var ax = ca.AxisX;
    var ay = ca.AxisY;
    

    Now let's hide the y-axis:

    ay.LineWidth = 0;
    

    To draw the portion of the axis from the interval offset to the maximum we simply code the PostPaint event:

    private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
    {
        // add references..
        ..
        // then use values to calulate pixel coordinates..
        int py1 = (int)ay.ValueToPixelPosition(ay.Minimum + ay.IntervalOffset);
        int py2 = (int)ay.ValueToPixelPosition(ay.Maximum);
        int px  = (int)ax.ValueToPixelPosition(ax.Maximum -  ax.Minimum);
    
        // blue to make it stand out
        e.ChartGraphics.Graphics.DrawLine(Pens.Blue, px, py1, px, py2);
    }
    

    Result:

    enter image description here

    Of course finding the right values for Interval, IntervalOffset, Minimum and Maximum is all up to you..

    Update: If you want to have a full set of shortened x-axis gridlines you could do a lot of math or use a graphics transform. As usual the latter is so much easier..:

    Graphics g = e.ChartGraphics.Graphics;
    int pyc = (int)ay.ValueToPixelPosition(ay.Minimum);  // y-center
    for (int i = 0; i < 360 / ax.Interval; i++)
    {
        g.TranslateTransform(px, pyc);
        g.RotateTransform((float)(i * ax.Interval));
        g.TranslateTransform(-px, -pyc);
        g.DrawLine(Pens.colorOfYourChoice, px, py1, px, py2);
        g.ResetTransform();
    }
    

    After setting ax.Interval = 30; we get this result:

    enter image description here