简体   繁体   English

从X值获取整个.NET图表系列的Y值

[英]Get Y value across .NET chart series from X value

using C# with .NET chart. .NET图表使用C#。

I am trying to graph several waveforms, and I wish to move my mouse across the chart area, and have my tooltip display the Y value of each series in the chart at this X value location. 我正在尝试绘制几个波形图,并且希望在图表区域上移动鼠标,并让我的工具提示在此X值位置显示图表中每个系列的Y值。

|      at xValue 12    |                                     |
|      _ = 3           |                                     |
|      * = 2           |                                * *  |
|              ________|______________________________*_____ |
|             /        |                             *       |
| __________*/*********|*****************************        |
|        *             |                                     |
|       *              |                                     |
|______________________|_____________________________________|

Kind of like this diagram above. 有点像上面这张图。 Below is a version of my code: 以下是我的代码的一个版本:

void chart1_MouseMove(object sender, MouseEventArgs e)
        {
            var pos = e.Location;
            _point.X = e.Location.X;
            _point.Y = e.Location.Y;

            try
            {
                if ((chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X) >= 0) && (chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X) <= max))
                {
                    //Crossair
                    chart1.ChartAreas[0].CursorX.SetCursorPixelPosition(_point, true);

                    //Tooltips
                    double xValue = chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X);
                    double yValue = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y);
                    string all_Data_Values = "";

                    foreach (var series in chart1.Series)
                    {
                        all_Data_Values = all_Data_Values + Environment.NewLine + series.Name + ": " + yValue;
                    }

                    tooltip.Show("At " + Math.Truncate(xValue * 1000) / 1000 + all_Data_Values, this.chart1, pos.X - 40, pos.Y - 20);
                }
            }
            catch (Exception exception)
            {
               //
            }
        }

This is what I have, and right now it only displays the Y value of my mouse cursor location. 这就是我所拥有的,现在它仅显示鼠标光标位置的Y值。 I have tried other codes, trying to somehow map the x values into chart1.Series[] but it didn't work either. 我尝试了其他代码,试图以某种方式将x值映射到chart1.Series [],但它也不起作用。

(This is in response to the request for code to look up the nearest value given a pixel coord.) (这是对代码请求的回应,该代码要求在给定像素坐标的情况下查找最接近的值。)

I'm doing it a bit differently from you, because I'm actually setting the chart's "cursor" as the user moves the mouse around, but hopefully this will give you enough information for you to adapt it to your needs... 我的操作与您的操作有所不同,因为实际上是在用户移动鼠标时设置图表的“光标”,但是希望这会为您提供足够的信息,以使其适合您的需求...

Here's how I calculate the X axis coord for a client X coord: 这是我为客户端X坐标计算X轴坐标的方法:

private double calcCursorGraphX(int clientX)
{
    var xAxis = _chart.ChartAreas[CHART_INDEX].AxisX;
    int xRight = (int) xAxis.ValueToPixelPosition(xAxis.Maximum) - 1;
    int xLeft = (int) xAxis.ValueToPixelPosition(xAxis.Minimum);

    if (clientX > xRight)
    {
        return xAxis.Maximum;
    }
    else if (clientX < xLeft)
    {
        return xAxis.Minimum;
    }
    else
    {
        return xAxis.PixelPositionToValue(clientX);
    }
}

Given an X value returned from the above method, we can look up the nearest preceeding value: 给定从上述方法返回的X值,我们可以查找最接近的先前值:

private int nearestPreceedingValue(double x)
{
    var bpData  = _chart.Series[SERIES_INDEX].Points;
    int bpIndex = bpData.BinarySearch(x, (xVal, point) => Math.Sign(x - point.XValue));

    if (bpIndex < 0)
    {
        bpIndex = ~bpIndex;                // BinarySearch() returns the index of the next element LARGER than the target.
        bpIndex = Math.Max(0, bpIndex-1);  // We want the value of the previous element, so we must decrement the returned index.
    }                                      // If this is before the start of the graph, use the first valid data point.

    return bpIndex;
}

Then you have an index which you can use to look up the value from _chart.Series[SERIES_INDEX].Points 然后,您就有一个索引,可用于从_chart.Series[SERIES_INDEX].Points查找值。

I'm not sure if this fits with the way that your data is stored in the charts, but that's how I do it. 我不确定这是否适合您的数据在图表中存储的方式,但这就是我的方式。

[EDIT] Here's the missing BinarySearch extension method. [编辑]这是缺少的BinarySearch扩展方法。 Add it to a static class somewhere accessible. 将其添加到可访问的静态类中。 Replace the "Contracts" stuff with your own error handling if you're not using Code Contracts. 如果您不使用代码合同,则用自己的错误处理替换“合同”内容。

/// <summary>
/// Searches the entire sorted IList{T} for an element using the specified comparer 
/// and returns the zero-based index of the element.
/// </summary>
/// <typeparam name="TItem">The type of the item.</typeparam>
/// <typeparam name="TSearch">The type of the searched item.</typeparam>
/// <param name="list">The list to be searched.</param>
/// <param name="value">The value to search for.</param>
/// <param name="comparer">The comparer that is used to compare the value with the list items.</param>
/// <returns>
/// The zero-based index of item in the sorted IList{T}, if item is found; 
/// otherwise, a negative number that is the bitwise complement of the index of the next element that is larger than item,
/// or - if there is no larger element - the bitwise complement of Count.
/// </returns>

public static int BinarySearch<TItem, TSearch>(this IList<TItem> list, TSearch value, Func<TSearch, TItem, int> comparer)
{
    Contract.Requires(list != null);
    Contract.Requires(comparer != null);

    int lower = 0;
    int upper = list.Count - 1;

    while (lower <= upper)
    {
        int middle = lower + (upper - lower) / 2;
        int comparisonResult = comparer(value, list[middle]);

        if (comparisonResult < 0)
        {
            upper = middle - 1;
        }
        else if (comparisonResult > 0)
        {
            lower = middle + 1;
        }
        else
        {
            return middle;
        }
    }

    return ~lower;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM