问题
I'm using JFreeChart
to draw chart. I have XYSeries with points (0, 0), (1, 2), (2, 5) and I want to read Y value for let's say x=1.5.
Is it possible to read value for points which are not in XYSeries? I couldn't find similar topic.
回答1:
This is not supported directly. It does not make sense in many cases: There simply is no data available for x=1.5. The value there could be 1000.0, or -3.141. You don't know.
However, you're most likely looking for a linear interpolation. The pragmatic approach is thus to find the interval that contains the respective x-value, and interpolate the y-values linearly.
There are some technical caveats. E.g. the XYSeries
may be not sorted, or may contain duplicate x-values, in which case there is no unique y-value for a given x-value. But for now, we can assume that the data set does not have these properties.
The following is an example of how this could be implemented. Note that this is not very efficient. If you have to compute many intermediate values (that is, if you intend to call the interpolate
method very often), it would be beneficial to create a tree-based data structure that allows looking up the interval in O(logn).
However, if this is not time critical (e.g. if you only intend to show the value in a tooltip or so), you may interpolate the values like this:
import java.util.List;
import org.jfree.data.xy.XYDataItem;
import org.jfree.data.xy.XYSeries;
public class XYInterpolation
{
public static void main(String[] args)
{
XYSeries s = new XYSeries("Series");
s.add(0,0);
s.add(1,2);
s.add(2,5);
double minX = -0.5;
double maxX = 3.0;
int steps = 35;
for (int i=0; i<=steps; i++)
{
double a = (double)i / steps;
double x = minX + a * (maxX - minX);
double y = interpolate(s, x);
System.out.printf("%8.3f : %8.3f\n", x, y);
}
}
private static double interpolate(XYSeries s, double x)
{
if (x <= s.getMinX())
{
return s.getY(0).doubleValue();
}
if (x >= s.getMaxX())
{
return s.getY(s.getItemCount()-1).doubleValue();
}
List<?> items = s.getItems();
for (int i=0; i<items.size()-1; i++)
{
XYDataItem i0 = (XYDataItem) items.get(i);
XYDataItem i1 = (XYDataItem) items.get(i+1);
double x0 = i0.getXValue();
double y0 = i0.getYValue();
double x1 = i1.getXValue();
double y1 = i1.getYValue();
if (x >= x0 && x <= x1)
{
double d = x - x0;
double a = d / (x1-x0);
double y = y0 + a * (y1 - y0);
return y;
}
}
// Should never happen
return 0;
}
}
(This implementation clamps at the limits. This means that for x-values that are smaller than the minimum x-value or larger than the maximum x-value, the y-value of the minimum/maximum x-value will be returned, respectively)
来源:https://stackoverflow.com/questions/26969188/how-to-get-y-value-from-x-value-in-jfreechart