简体   繁体   中英

How to find the nearest point in the chart?

.net 4 vs2010 winform c#

added some points using

chart1.Series[0].Points.AddXY(x,y);

when I click on the chart, the cursor may not fall on any points. Are there any functions to return the nearest point? (forget y, just x distance.) Or I have to write my own binary search function?

private void Chart_MouseClick(object sender, MouseButtonEventArgs e)
{
    LineSeries line = (LineSeries)mychart.Series[0];
    Point point = e.GetPosition(line);
    Int32? selectIndex = FindNearestPointIndex(line.Points, point);

    // ...
}

private Int32? FindNearestPointIndex(PointCollection points, Point point)
{
    if ((points == null || (points.Count == 0))
        return null;

    Func<Point, Point, Double> getLength = (p1, p2) => Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2)); // C^2 = A^2 + B^2
    List<Points> results = points.Select((p,i) => new { Point = p, Length = getLength(p, point), Index = i }).ToList();
    Int32 minLength = results.Min(i => i.Length);

    return results.First(i => (i.Length == minLength)).Index;
}

To find the nearest point in a set of unordered points, you have to iterate through them all and keep track of the minimum distance. This has a time complexity of O(n).

You could significantly improve this by maintaining the points in a more organized data structure (such as an R-tree ). There are third-party libraries available if you'd rather not implement your own. Many databases already support the R-tree for spatial indices.

If you really want to only search for the point with the nearest X-coordinate, this could be further simplified by storing the points in a sorted collection (such as a SortedList<TKey, TValue> ) and performing a binary search (which SortedList<TKey, TValue>.IndexOfKey already implements).

/*My Fuzzy Binary Search*/
private int FindNearestId(System.Windows.Forms.DataVisualization.Charting.DataPointCollection p, uint ClickedX)
{
    int ret = 0;
    int low = 0;
    int high = p.Count - 1;
    bool bLoop = true;

    while (bLoop)
    {
        ret = (low + high) / 2;
        switch (FindNearestId_Match(p, ClickedX, ret))
        {
        case 0:
            high = ret+1;
            break;
        case 1:
            bLoop = false;
            break;
        case 2:
            low = ret-1;
            break;
        }
    }

    return ret+1;
}

private int FindNearestId_Match(System.Windows.Forms.DataVisualization.Charting.DataPointCollection p, uint ClickedX, int id)
{
    uint id0 = Convert.ToUInt32(p[id].XValue);
    uint id1 = Convert.ToUInt32(p[id+1].XValue);

    if ( (id0 <= ClickedX) && (ClickedX < id1) )
    {
        return 1;
    }
    else if ((id0 < ClickedX) && (ClickedX > id1))
    {
        return 2;
    }
    else
    {
        return 0;
    }
}

Soultion can be more clear. ( as above you should use log complexity for accessing item )

double x-values solution:

double FindNearestPointYValueInSeries( System::Windows::Forms::DataVisualization::Charting::Series ^pxSeries, double dSearchedPosition )
{
    int i_min = 0;
    int i_max = pxSeries->Points->Count - 1;
    int i_mean = 0;
    double d ;

    if ( i_max < 0 ) // not defined - minimum one point required
        return Double::NaN;

    while ( i_min <= i_max )
    {
        i_mean = (i_max + i_min ) / 2; // index of compared value in series
        d = pxSeries->Points[ i_mean ]->XValue; // compared value 

        if ( d > dSearchedPosition ) // greater - search in right part
            i_max = i_mean - 1;
        else if ( d < dSearchedPosition ) // lower - search in left part
            i_min = i_mean + 1;
        else // equal ?
            return d;
    }

    // delta is dSearchedPosition - pxSeries->Points[ i_mean ]->YValues[0]

    // get Y value ( on index 0 ) 
    return pxSeries->Points[ i_mean ]->YValues[0];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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