以对数刻度显示刻度标签MS Chart(log-log)

时间:2016-05-15 22:41:24

标签: c# charts .net-4.5 mschart

我在Visual Studio 2015(C#)中使用MS图表创建了一个用对数刻度(两个轴)创建的图(见图)。

我需要在x轴上添加更多网格线和相应的标签。我想在1(2,3,4 ......)和10之间以及10到100(20,30,40 ......)之间标记每个次要标记,并且我还要在例如两者之间添加网格线。 10和20。

我在图表的轴属性中使用1的间隔作为标签,但它不起作用。

Chart with log scale

1 个答案:

答案 0 :(得分:4)

After(!) adding a point at a non-zero x-value or setting chart.SuppressExceptions = true you can use these properties for a Chartarea ca:

ca.AxisX.IsLogarithmic = true;
ca.AxisX.LogarithmBase = 10;

// with 10 as the base it will go to 1, 10, 100, 1000..
ca.AxisX.Interval = 1;

// this adds 4 tickmarks into each interval:
ca.AxisX.MajorTickMark.Interval = 0.25;

// this add 8 gridlines into each interval:
ca.AxisX.MajorGrid.Interval = 0.125;

// this sets two i.e. adds one extra label per interval
ca.AxisX.LabelStyle.Interval = 0.5;
ca.AxisX.LabelStyle.Format = "#0.0";

enter image description here

Update:

Since you don't want to have automatic labels (which are always aligned by value) you need to add CustomLabels.

For this you need to set up a list of positions/values where you want a label to show:

    // pick a better name!
    List<double> xs = new List<double>() { 1, 2, 3, 4, 5, 10, 20, 50, 100, 200, 500, 1000};

Next we need to assign a FromPosition and a ToPosition to each CustomLabel we create. This is always a little tricky but here even more than usual..

The two values need to be spaced far enough to allow a label to fit in.. So we pick a spacer-factor:

    double spacer = 0.9d;

And we also turn off the auto-fitting mechanism:

    ca.AxisX.IsLabelAutoFit = false;

Now we can add the CustomLabels:

    for (int i = 0; i < xs.Count; i++)
    {
        CustomLabel cl = new CustomLabel();
        if (xs[i] == 1 || xs[i] <= 0)
        {
            cl.FromPosition = 0f;
            cl.ToPosition = 0.01f;
        }
        else
        {
            cl.FromPosition = Math.Log10(xs[i] * spacer);
            cl.ToPosition = Math.Log10(xs[i] / spacer);
        }

        cl.Text = xs[i] + "";
        ca.AxisX.CustomLabels.Add(cl);

    }

As you can see we need to calculate the values using the Log10 function that is applied to the Axis and the spacing is achieved by multiplying/dividing the spacer, not by adding. The spacing value must also be scaled by Log10 and is included in the function.

We also need to take care of the case of a value of 1, which amounts to a label position of 0; but this won't result in any spacing when multiplying/dividing it. So we set a suitable ToPosition manually.

I wish I knew of an easier way to do this, but as the list of label positions is really your choice, I doubt there is a short-cut..

enter image description here

I have added points at 40 and 50 to show how one label matches.. Also note how the label positions are somewhat mixed. Feel free to use yours!

相关问题