我有一个对数-对数图,两个轴的范围都在0.1到1000之间。我希望每十年只有1个主要刻度。到目前为止,除了设置这段代码中的IntervalLength之外,我没有其他方法可以控制刻度线间距。
var logxAxis = new LogarithmicAxis
{
Position = AxisPosition.Bottom,
Title = "Resistivity of Approaching Bed (ohm-m)",
IntervalLength = 100,
MajorGridlineStyle = LineStyle.Solid,
MinorGridlineStyle = LineStyle.None,
MinorTickSize = 0.0,
Key = "logx"
};
默认的IntervalLength为60,这使我每10跳一跳。不幸的是,随着我增加应用程序的窗口大小,主要报价的数量也增加了。因此,设置IntervalLength并不是理想的解决方案。我已经查看了OxyPlot的源代码,却一无所获。我是否缺少某些东西,或者可能需要派生自己的LogarithmicAxis类?
编辑:我决定导出自己的对数轴,并替换生成的刻度线的函数。
public override void GetTickValues(out IList<double> majorLabelValues, out IList<double> majorTickValues,
out IList<double> minorTickValues)
{
majorLabelValues = new List<double> { 0.1, 1, 10, 100, 1000 };
majorTickValues = new List<double> { 0.1, 1, 10, 100, 1000 };
minorTickValues = new List<double>();
}
这至少可以让我把应用程序拿出来。
答案 0 :(得分:1)
经过一番思考,我决定对coding子进行硬编码不是最好的主意。我决定创建一个对数轴,在其中可以锁定刻度线的位置,但也可以解锁,并让OxyPlot的内置算法起作用。您会发现我重用了一些内部的OxyPlot方法,因此我只是将代码复制到了我的类中并使其私有。通过访问代码可以更轻松地解决此问题。我愿意听其他解决方案。
public class LockableLogarithmicAxis : LogarithmicAxis
{
#region Properties
public bool IsLocked { get; set; }
public double[] MajorTickPositions { get; set; }
public double[] MinorTickPositions { get; set; }
#endregion
#region Constructor
public LockableLogarithmicAxis()
{
IsLocked = true;
}
#endregion
#region Methods
public override void GetTickValues(out IList<double> majorLabelValues, out IList<double> majorTickValues,
out IList<double> minorTickValues)
{
if (!IsLocked)
{
base.GetTickValues(out majorLabelValues, out majorTickValues, out minorTickValues);
return;
}
if (MajorTickPositions != null && MajorTickPositions.Length > 0)
{
majorTickValues = MajorTickPositions.ToList();
}
else
{
majorTickValues = this.DecadeTicks();
}
if (MinorTickPositions != null && MinorTickPositions.Length > 0)
{
minorTickValues = MinorTickPositions.ToList();
}
else
{
minorTickValues = this.SubdividedDecadeTicks();
}
majorLabelValues = majorTickValues;
}
/// <summary>
/// Calculates ticks of the decades in the axis range with a specified step size.
/// </summary>
/// <param name="step">The step size.</param>
/// <returns>A new IList containing the decade ticks.</returns>
private IList<double> DecadeTicks(double step = 1)
{
return this.PowList(this.LogDecadeTicks(step));
}
/// <summary>
/// Calculates logarithmic ticks of the decades in the axis range with a specified step size.
/// </summary>
/// <param name="step">The step size.</param>
/// <returns>A new IList containing the logarithmic decade ticks.</returns>
private IList<double> LogDecadeTicks(double step = 1)
{
var ret = new List<double>();
if (step > 0)
{
var last = double.NaN;
for (var exponent = Math.Ceiling(this.LogActualMinimum); exponent <= this.LogActualMaximum; exponent += step)
{
if (exponent <= last)
{
break;
}
last = exponent;
if (exponent >= this.LogActualMinimum)
{
ret.Add(exponent);
}
}
}
return ret;
}
/// <summary>
/// Raises all elements of a List to the power of <c>this.Base</c>.
/// </summary>
/// <param name="logInput">The input values.</param>
/// <param name="clip">If true, discards all values that are not in the axis range.</param>
/// <returns>A new IList containing the resulting values.</returns>
private IList<double> PowList(IList<double> logInput, bool clip = false)
{
return
logInput.Where(item => !clip || !(item < this.LogActualMinimum))
.TakeWhile(item => !clip || !(item > this.LogActualMaximum))
.Select(item => Math.Pow(this.Base, item))
.ToList();
}
/// <summary>
/// Calculates ticks of all decades in the axis range and their subdivisions.
/// </summary>
/// <param name="clip">If true (default), the lowest and highest decade are clipped to the axis range.</param>
/// <returns>A new IList containing the decade ticks.</returns>
private IList<double> SubdividedDecadeTicks(bool clip = true)
{
var ret = new List<double>();
for (var exponent = (int)Math.Floor(this.LogActualMinimum); ; exponent++)
{
if (exponent > this.LogActualMaximum)
{
break;
}
var currentDecade = Math.Pow(this.Base, exponent);
for (var mantissa = 1; mantissa < this.Base; mantissa++)
{
var currentValue = currentDecade * mantissa;
if (clip && currentValue < this.ActualMinimum)
{
continue;
}
if (clip && currentValue > this.ActualMaximum)
{
break;
}
ret.Add(currentDecade * mantissa);
}
}
return ret;
}
#endregion
}