2014-11-17 4 views
1

Я использую JFreeChart для рисования графика. У меня есть XYSeries с точками (0, 0), (1, 2), (2, 5), и я хочу прочитать значение Y, скажем, x = 1.5.Как получить значение Y из значения X в JFreeChart

Можно ли читать значение для точек, которые не находятся в XYSeries? Я не мог найти подобную тему.

ответ

2

Это не поддерживается напрямую. Это не имеет смысла во многих случаях: Просто нет данных для x = 1.5. Значение может быть 1000.0 или -3.141. Вы не знаете.

Однако вы, скорее всего, ищете линейную интерполяцию. Таким образом, прагматический подход заключается в том, чтобы найти интервал, который содержит соответствующее значение x, и линейно интерполировать значения y.

Есть некоторые технические оговорки. Например. XYSeries могут не сортироваться или содержать повторяющиеся значения x, и в этом случае для данного значения x не существует единственного значения y. Но пока мы можем предположить, что набор данных не обладает этими свойствами.

Ниже приведен пример того, как это можно реализовать. Обратите внимание, что это не очень эффективно. Если вам нужно вычислить много промежуточных значений (то есть, если вы намерены часто называть метод interpolate), было бы полезно создать древовидную структуру данных, которая позволяет искать интервал в O (logn).

Однако, если это не критично по времени (например, если вы только собираетесь показать значение в подсказке или около того), вы можете интерполировать значения, как это:

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; 
    } 

} 

(Эту реализацию зажимает в пределах. Это означает, что для значений x, которые меньше минимального значения x или больше максимального значения x, будет возвращено значение y минимального/максимального x-значения соответственно)

+0

Спасибо, это действительно помогло. – user3626048

Смежные вопросы