在悬停时突出显示 winforms MS 图表线

Highlight winforms MS Chart line on hover

我正在尝试将 MS Chart 与自定义控件结合使用。我的目的是:

插图种类:

现在,我可以使用 中描述的方法检测图表上一条线上的悬停。但我一直在寻找索引或至少是这两点的坐标。

所以最初的想法是通过x找到最近的点(假设所有的系列都有x值确实在稳步增加)然后计算y值。但我对此做了一些改进,并增加了对完全垂直线的支持。所以这是我捕获所需行的代码:

 private static GrippedLine? LineHitTest(Series series, double xPos, double yPos, Axis xAxis, Axis yAxis)
    {
        double xPixelPos = xAxis.PixelPositionToValue(xPos);
        double yPixelPos = yAxis.PixelPositionToValue(yPos);
        DataPoint[] neighbors = new DataPoint[2];
        neighbors[0] = series.Points.Last(x => x.XValue <= xPixelPos);
        neighbors[1] = series.Points.First(x => x.XValue >= xPixelPos);

        DataPoint[] verticalMates;
        foreach (DataPoint neighbor in neighbors)
        {
            if (Math.Abs(neighbor.XValue - xPixelPos) < LINE_GRIP_REGION)
            {
                verticalMates = series.Points.FindAllByValue(neighbor.XValue, "X").ToArray();
                if (verticalMates.Length > 1)
                {
                    if (verticalMates.Length > 2)
                    {
                        if (verticalMates[0].YValues[0] < verticalMates[verticalMates.Length - 1].YValues[0])
                        {
                            neighbors[0] = verticalMates.LastOrDefault(y => y.YValues[0] < yPixelPos);
                            neighbors[1] = verticalMates.FirstOrDefault(y => y.YValues[0] >= yPixelPos);
                        }
                        else
                        {
                            neighbors[0] = verticalMates.LastOrDefault(y => y.YValues[0] > yPixelPos);
                            neighbors[1] = verticalMates.FirstOrDefault(y => y.YValues[0] <= yPixelPos);
                        }
                    }
                    else
                    {
                        neighbors[0] = verticalMates[0];
                        neighbors[1] = verticalMates[1];
                    }
                    break;
                }
            }
        }

        double x0 = xAxis.ValueToPixelPosition(neighbors[0].XValue);
        double y0 = yAxis.ValueToPixelPosition(neighbors[0].YValues[0]);

        double x1 = xAxis.ValueToPixelPosition(neighbors[1].XValue);
        double y1 = yAxis.ValueToPixelPosition(neighbors[1].YValues[0]);

        double Yinterpolated = y0 + (y1 - y0) * (xPos - x0) / (x1 - x0);

        int[] linePoints = new int[2];
        // if mouse Y position is near the calculated OR the line is vertical
        if (Math.Abs(Yinterpolated - yPos) < LINE_GRIP_REGION || neighbors[0].XValue == neighbors[1].XValue)
        {
            linePoints[0] = series.Points.IndexOf(neighbors[0]);
            linePoints[1] = series.Points.IndexOf(neighbors[1]);

        }
        else
        {
            return null;
        }
        return new GrippedLine()
        {
            startLinePointIndex = linePoints[0],
            endLinePointIndex = linePoints[1],
            x0Correction = neighbors[0].XValue - xPixelPos,
            y0Correction = neighbors[0].YValues[0] - yPixelPos,
            x1Correction = neighbors[1].XValue - xPixelPos,
            y1Correction = neighbors[1].YValues[0] - yPixelPos
        };
    }