.net 4 VS2010 WinForm的 C#
使用
添加了一些观点chart1.Series[0].Points.AddXY(x,y);
当我点击图表时,光标可能不会落在任何点上。 有没有函数返回最近的点? (忘了y,只是x距离。) 或者我必须编写自己的二进制搜索功能?
答案 0 :(得分:1)
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;
}
答案 1 :(得分:1)
要在一组无序点中找到最近的点,您必须遍历它们并跟踪最小距离。这的时间复杂度为O(n)。
您可以通过在更有条理的数据结构(例如R-tree)中维护点来显着改善这一点。如果您不想实现自己的库,可以使用第三方库。许多数据库已经支持空间索引的R树。
如果您真的只想搜索具有最近X坐标的点,可以通过将点存储在已排序的集合(例如SortedList<TKey, TValue>
)中并执行二进制搜索(其中SortedList<TKey, TValue>.IndexOfKey
已经实施了。)
答案 2 :(得分:0)
/*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;
}
}
答案 3 :(得分:0)
解决方案可以更清晰。 (如上所述,您应该使用日志复杂性来访问项目)
双x值解决方案:
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];
}