I am using the new WPF toolkit's Chart to plot large data sets. I also have a crosshair tracker that follows the mouse when it's over the chart area to tell exactly what is the value of the nearest data point (see Yahoo! Finance charts).
I use the following code to find the closest data point that is lower (or equal) to where the mouse is currently hovering (the nasty detail about the chart is that it actually interpolates the data to tell you what's the EXACT value where you hove your mouse over, even though the mouse is located between the data points):
TimeDataPoint point = mainSeries.Find(
new Predicate<TimeDataPoint>(
delegate(TimeDataPoint p) {
return xValue > p.Date && !mainSeries.Exists(new Predicate<TimeDataPoint>(
delegate(TimeDataPoint middlePoint) {
return middlePoint.Date > p.Date && xValue > middlePoint.Date;
}));
}));
[Here, mainSeries
is simply a List<TimeDataPoint>
]
This works very well for relatively small data sets, but once I go up to 12000+ points (this will increase rapidly), the code above slows down to a standstill (it does a run through data 12000+^2 times).
I am not very good at constructing queries so I am wondering if it is possible to use a better LINQ query to do this.
EDIT: Another idea that was inspired by @Randolpho comment is this: I will search for all points that are lower than given (this will be at most n (here: 12,000+)) and then select a Max<> (which should be also at most O(n)). This should produce the same result but only with order of n operations and thus should be at least a little bit faster...
My other alternative is to actually filter the data set and maintain an upper bound on the number of points depending on the level of details the user wants to see. I would rather not go down that road if there's a possibility of having a more efficient query.