2009-05-18 20 views
18

Mam nadzieję, że znajdę prostą bibliotekę, która może przyjąć serię punktów dwuwymiarowych i zwróci mi większą liczbę punktów, które modelują krzywą. Zasadniczo, chcę uzyskać efekt dopasowania krzywej jak to próbki z JFreeChart:Biblioteka dopasowania krzywej Java

alt text http://www.jfree.org/jfreechart/images/XYSplineRendererDemo1a.png

Problem z JFreeChart jest, że kod nie przewiduje tego typu API. Spojrzałem nawet na źródło i algorytm jest ściśle powiązany z rzeczywistym rysunkiem.

+0

pytań jest „zawieszone”: Można by przeformułować pytanie dać przykład kodu w Javie krzywej Kod przyłącza (oczywiście, że kod będzie ciągnąć w niektórych bibliotekach, tak widać to jako zalecenie). To pytanie nie dotyczy JFreeChart, które po prostu ZAJWUJE punkty i wyświetla je, ale nie generuje dodatkowych punktów. Jestem zaskoczony, że Linked i Related nie pokazują dokładnie tego pytania. –

Odpowiedz

0

nigdy nie zrobił, ale szybkie wyszukiwanie Google ujawniło, że krzywe Beziera są realizowane w http://java.sun.com/j2se/1.5.0/docs/api/java/awt/geom/QuadCurve2D.Double.html

Następnie można getPathIterator() z tej krzywej i że zgodnie z tym co mówi dokumentacji, można uzyskać "współrzędne granic kształtu", co, jak przypuszczam, jest tym, czego szukasz.

+1

Nie, on nie chce tego robić. Musi on obliczyć punkty kontrolne krzywej za pomocą interpolacji spline lub pewnej metody heurystycznej. – Matej

+0

Sugeruję, że lepiej przeczytać http://pl.wikipedia.org/wiki/Spline_(mathematics) i http://pl.wikipedia.org/wiki/B%C3%A9zier_curve Krzywe Beziera są jednym ze sposobów modeluj te krzywe. Dzięki współrzędnym punktów na tej krzywej, on faktycznie dostaje to, czego chce. – jbasko

4

Apache Commons Math ma przyjemny szereg algorytmów, w szczególności „SplineInterpolator” zobacz API docs

przykładem, w którym wywołanie funkcji interpolacji alfa (X) p (x) od Groovy:

package example.com 

import org.apache.commons.math3.analysis.interpolation.SplineInterpolator 
import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction 

import statec.Extrapolate.Value; 

class Interpolate { 

    enum Value { 
     ALPHA, BETA 
    } 

    def static xValues  = [ 
     -284086, 
     -94784, 
     31446, 
     354837, 
     667782, 
     982191 
    ] 
    def static alphaValues = [ 
     71641, 
     78245, 
     80871, 
     94045, 
     105780, 
     119616 
    ] 
    def static betaValues = [ 
     95552, 
     103413, 
     108667, 
     128456, 
     144686, 
     171953 
    ] 

    static def getValueByName(Value value, int i) { 
     def res 
     switch (value) { 
      case Value.ALPHA: 
       res = alphaValues[i] 
       break 
      case Value.BETA: 
       res = betaValues[i] 
       break 
      default: 
       assert false 
     } 
     return res 
    } 

    static PolynomialSplineFunction interpolate(Value value) { 
     def yValues = [] 
     int i = 0 
     xValues.each { 
      def y = getValueByName(value, i++) 
      yValues << (y as Double) 
     } 
     SplineInterpolator spi = new SplineInterpolator() 
     return spi.interpolate(xValues as double[], yValues as double[]) 
    } 

    static void main(def argv) { 
     // 
     // Create a map mapping a Value instance to its interpolating function 
     // 
     def interpolations = [:] 
     Value.values().each { 
      interpolations[it] = interpolate(it) 
     } 
     // 
     // Create an array of new x values to compute display. 
     // Make sure the last "original" value is in there! 
     // Note that the newxValues MUST stay within the range of the original xValues! 
     // 
     def newxValues = [] 
     for (long x = xValues[0] ; x < xValues[-1] ; x+=25000) { 
      newxValues << x 
     } 
     newxValues << xValues[-1] 
     // 
     // Write interpolated values for ALPHA and BETA, adding the original values in columns 4 and 5 
     // 
     System.out << "X , ALPHA, BETA, X_orig, ALPHA_orig, BETA_orig" << "\n" 
     int origIndex = 0 
     newxValues.each { long x -> 
      def alpha_ipol = interpolations[Value.ALPHA].value(x) 
      def beta_ipol = interpolations[Value.BETA].value(x) 
      String out = "${x} , ${alpha_ipol} , ${beta_ipol}" 
      if (x >= xValues[origIndex]) { 
       out += ", ${xValues[origIndex]}, ${alphaValues[origIndex]}, ${betaValues[origIndex]}" 
       origIndex++ 
      } 
      System.out << out << "\n" 
     } 
    } 
} 

The resulting output, plotted in LibreOffice Calc

A teraz przykład poza tematem dla ekstrapolacji, bo to zabawa. Tutaj używamy tych samych danych jak powyżej, ale ekstrapolujemy za pomocą wielomianu 2 stopnia. I oczywiście odpowiednie klasy. Ponownie, w Groovy:

package example.com 

import org.apache.commons.math3.analysis.polynomials.PolynomialFunction 
import org.apache.commons.math3.fitting.PolynomialFitter 
import org.apache.commons.math3.fitting.WeightedObservedPoint 
import org.apache.commons.math3.optim.SimpleVectorValueChecker 
import org.apache.commons.math3.optim.nonlinear.vector.jacobian.GaussNewtonOptimizer 

class Extrapolate { 

    enum Value { 
     ALPHA, BETA 
    } 

    def static xValues  = [ 
     -284086, 
     -94784, 
     31446, 
     354837, 
     667782, 
     982191 
    ] 
    def static alphaValues = [ 
     71641, 
     78245, 
     80871, 
     94045, 
     105780, 
     119616 
    ] 
    def static betaValues = [ 
     95552, 
     103413, 
     108667, 
     128456, 
     144686, 
     171953 
    ] 

    static def getValueByName(Value value, int i) { 
     def res 
     switch (value) { 
      case Value.ALPHA: 
       res = alphaValues[i] 
       break 
      case Value.BETA: 
       res = betaValues[i] 
       break 
      default: 
       assert false 
     } 
     return res 
    } 

    static PolynomialFunction extrapolate(Value value) { 
     // 
     // how to check that we converged 
     // 
     def checker 
     A: { 
      double relativeThreshold = 0.01 
      double absoluteThreshold = 10 
      int maxIter = 1000 
      checker = new SimpleVectorValueChecker(relativeThreshold, absoluteThreshold, maxIter) 
     } 
     // 
     // how to fit 
     // 
     def fitter 
     B: { 
      def useLUdecomposition = true 
      def optimizer = new GaussNewtonOptimizer(useLUdecomposition, checker) 
      fitter = new PolynomialFitter(optimizer) 
      int i = 0 
      xValues.each { 
       def weight = 1.0 
       def y = getValueByName(value, i++) 
       fitter.addObservedPoint(new WeightedObservedPoint(weight, it, y)) 
      } 
     } 
     // 
     // fit using a 2-degree polynomial; guess at a linear function at first 
     // "a0 + (a1 * x) + (a2 * x²)"; a linear guess mean a2 == 0 
     // 
     def params 
     C: { 
      def mStart = getValueByName(value,0) 
      def mEnd = getValueByName(value,-1) 
      def xStart = xValues[0] 
      def xEnd = xValues[-1] 
      def a2 = 0 
      def a1 = (mEnd - mStart)/(xEnd - xStart) // slope 
      def a0 = mStart - (xStart * a1) // 0-intersection 
      def guess = [a0 , a1 , a2] 
      params = fitter.fit(guess as double[]) 
     } 
     // 
     // make polynomial 
     // 
     return new PolynomialFunction(params) 
    } 

    static void main(def argv) { 
     // 
     // Create a map mapping a Value instance to its interpolating function 
     // 
     def extrapolations = [:] 
     Value.values().each { 
      extrapolations[it] = extrapolate(it) 
     } 
     // 
     // New x, this times reaching out past the range of the original xValues 
     // 
     def newxValues = [] 
     for (long x = xValues[0] - 400000L ; x < xValues[-1] + 400000L ; x += 10000) { 
      newxValues << x 
     } 
     // 
     // Write the extrapolated series ALPHA and BETA, adding the original values in columns 4 and 5 
     // 
     System.out << "X , ALPHA, BETA, X_orig, ALPHA_orig, BETA_orig" << "\n" 
     int origIndex = 0 
     newxValues.each { long x -> 
      def alpha_xpol = extrapolations[Value.ALPHA].value(x) 
      def beta_xpol = extrapolations[Value.BETA].value(x) 
      String out = "${x} , ${alpha_xpol} , ${beta_xpol}" 
      if (origIndex < xValues.size() && x >= xValues[origIndex]) { 
       out += ", ${xValues[origIndex]}, ${alphaValues[origIndex]}, ${betaValues[origIndex]}" 
       origIndex++ 
      } 
      System.out << out << "\n" 
     } 
    } 
} 

The resulting output, plotted in LibreOffice Calc