Автоматическое масштабирование оси Y на оси X Масштабирование

Да, я знаю о (этом сообщении), если при поиске вы заметите, что событие AxisValueChanged, похоже, существует только в этом одном потоке.

Моя цель - просто автоматически масштабировать ось Y, когда пользователь делает выбор по оси X, но я не смог понять, как это сделать.

Я также попытался использовать событие SelectionRangeChanged, но это событие кажется сломанным, так как я не могу понять, какой фактический диапазон выбран? (IE, чтобы я мог найти максимальные / минимальные диапазоны).

Я использую диаграмму MS (диаграмма Microsoft)

Конечная цель - когда я увеличиваю ось X (это диаграмма FastLine), она должна увидеть новое «максимальное» видимое значение по оси Y и соответственно изменить его размер / масштаб.


person EKS    schedule 17.04.2012    source источник


Ответы (1)


Если я вас правильно понимаю, учитывая увеличенный диапазон по оси X, вы хотите увеличить также тот же диапазон по оси Y. Если да, то можно сделать так:

void chart1_SelectionRangeChanged(object sender, CursorEventArgs e)
{
    // Given the visible (zoomed) range on X, 
    // it zooms the same relative range on Y:
    // i.e. if on the X axis, the range 5% - 30% is zoomed, 
    // it zooms the same range on Y.
    var axisY = this.chart1.ChartAreas[0].AxisY;

    var totalXRange = e.Axis.Maximum - e.Axis.Minimum;
    var totalYRange = axisY.Maximum - axisY.Minimum;

    var ySelectionStart = (e.Axis.ScaleView.ViewMinimum - e.Axis.Minimum) *
                          totalYRange / totalXRange;
    var ySelectionEnd = (e.Axis.ScaleView.ViewMaximum - e.Axis.Minimum) * 
                         totalYRange / totalXRange;

    axisY.ScaleView.Zoom(ySelectionStart,ySelectionEnd);
}

Как вы сказали, события AxisValueChanged не существует; сообщение, которое вы связали, вероятно, означало (существующее) событие AxisViewChanged.

Очевидно, вы также можете использовать AxisViewChanged для своих целей, и адаптировать мой код для использования этого события не должно быть так сложно.

Не стесняйтесь спрашивать, нужна ли вам помощь;)

РЕДАКТИРОВАТЬ:

Я изменил свой код, чтобы учесть вашу цель. Следующий код вычисляет диапазон Y, соответствующий максимальному и минимальному значениям точек внутри увеличенного диапазона X:

void chart1_SelectionRangeChanged(object sender, CursorEventArgs e)
{
    var axisY = this.chart1.ChartAreas[0].AxisY;

    var xRangeStart = e.Axis.ScaleView.ViewMinimum;
    var xRangeEnd = e.Axis.ScaleView.ViewMaximum;

    // compute the Y values for the points crossing the range edges
    double? yRangeStart = null;
    var pointBeforeRangeStart = this.chart1.Series[0].Points.FirstOrDefault(x => x.XValue <= xRangeStart);
    var pointAfterRangeStart = this.chart1.Series[0].Points.FirstOrDefault(x => x.XValue > xRangeStart);
    if (pointBeforeRangeStart != null && pointAfterRangeStart != null)
        yRangeStart = Interpolate2Points(pointBeforeRangeStart, pointAfterRangeStart, xRangeStart);

    double? yRangeEnd = null;
    var pointBeforeRangeEnd = this.chart1.Series[0].Points.FirstOrDefault(x => x.XValue <= xRangeEnd);
    var pointAfterRangeEnd = this.chart1.Series[0].Points.FirstOrDefault(x => x.XValue > xRangeEnd);
    if (pointBeforeRangeEnd != null && pointAfterRangeEnd != null)
        yRangeEnd = Interpolate2Points(pointBeforeRangeEnd, pointAfterRangeEnd, xRangeEnd);

    var edgeValues = new[] { yRangeStart, yRangeEnd }.Where(x => x.HasValue).Select(x => x.Value);

    // find the points inside the range
    var valuesInRange = this.chart1.Series[0].Points
    .Where(p => p.XValue >= xRangeStart && p.XValue <= xRangeEnd)
    .Select(x => x.YValues[0]);

    // find the minimum and maximum Y values
    var values = valuesInRange.Concat(edgeValues);
    double yMin;
    double yMax;
    if (values.Any())
    {
        yMin = values.Min();
        yMax = values.Max();
    }
    else
    {
        yMin = this.chart1.Series[0].Points.Min(x => x.YValues[0]);
        yMax = this.chart1.Series[0].Points.Max(x => x.YValues[0]);
    }

    // zoom Y-axis to [yMin - yMax]
    axisY.ScaleView.Zoom(yMin, yMax);
}

// see: http://en.wikipedia.org/wiki/Linear_interpolation#Linear_interpolation_between_two_known_points
public static double Interpolate2Points(DataPoint p1, DataPoint p2, double x)
{
    var x0 = p1.XValue;
    var y0 = p1.YValues[0];
    var x1 = p2.XValue;
    var y1 = p2.YValues[0];
    return y0 + ((x - x0) * y1 - (x - x0) * y0) / (x1 - x0);
}
person digEmAll    schedule 17.04.2012
comment
Это отлично работает, как я уже объяснял, я немного обновил объяснение, чтобы прояснить мою конечную цель. Иль лично тестирую еще завтра :) Спасибо - person EKS; 18.04.2012