Search code examples
c#chartslogarithm

How to put a logarithmic scale with rows represented in logarithm on chart in C #


I'm developing a chart in C # and I need the graph lines to be represented in logarithm, the scale can already put, just missing the vertical lines in logarithmic scale according to the image below:

enter image description here

My chart currently looks like this:

enter image description here


Solution

  • Update:

    To get those additional lines between the periods you need to turn on the MinorGrid for the x-axis of your chartArea:

    chart.ChartAreas[0].AxisX.MinorGrid.Enabled = true;
    chart.ChartAreas[0].AxisX.MinorGrid.Interval = 1;
    

    This is obviosly a lot easier than drawing them yourself, as I thought was necessary..

    I leave the owner-drawn solution below, though, as it may be useful when doing extra special stuff, like using unsusual pens or customizing the intervals..

    (And I was glad to see that the results are identical :-)

    enter image description here

    Old solution with owner-drawn GridLines:

    Here is how you can owner-draw the gridlines for a logarithmic axis.

    To define the interval rules I first collect a List of double values for the stop values. along the x-axis.

    Here is an example using 10 gridlines in each period..

    The chart's x-axis was set up with Minimum = 0.1d and Maximum = 1000.

    enter image description here

    private void chart_PrePaint(object sender, ChartPaintEventArgs e)
    {
        ChartArea ca = chart.ChartAreas[0];
        Graphics g = e.ChartGraphics.Graphics;
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    
        // first get y top and bottom values:
        int y0 = (int)ca.AxisY.ValueToPixelPosition(ca.AxisY.Minimum);
        int y1 = (int)ca.AxisY.ValueToPixelPosition(ca.AxisY.Maximum);
    
        int iCount = 10;                         // number of gridlines per period
        var xes = new List<double>();            // the grid position values
        double xx = ca.AxisX.Minimum;
        do {
           xx *= ca.AxisX.LogarithmBase;         // next period
           double delta = 1d * xx / iCount ;     // distance in this period
           for (int i = 1; i < icount; i++) xes.Add(i * delta);  // collect the values
        }  while (xx < ca.AxisX.Maximum);
    
        // now we can draw..
        using (Pen pen = new Pen(Color.FromArgb(64, Color.Blue))
              {DashStyle = System.Drawing.Drawing2D.DashStyle.Dot} )
           foreach (var xv in xes)
           {
               float x = (float)ca.AxisX.ValueToPixelPosition(xv);
               g.DrawLine(pen, x, y0, x, y1);
           }
    }
    

    You could cache the x-values list but would have to re-calculate whenever the data or the axis view changes..

    Note that, when collection the grid stop values, we count from 1 because we don't want to double the starting points of a period: 1..9 + 10..90 etc. So we actually add only count-1 grid stops..