2009-05-18 3 views
18

Ich hoffe, eine einfache Bibliothek zu finden, die eine Reihe von zweidimensionalen Punkten nehmen kann und mir eine größere Reihe von Punkten zurückgibt, die die Kurve modellieren. Grundsätzlich mag ich die Wirkung der Kurve wie dieses Beispiel aus JFreeChart passend erhalten:Java Kurvenanpassung Bibliothek

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

Das Problem mit JFreeChart ist, dass der Code nicht diese Art von api bietet. Ich schaute sogar auf die Quelle und der Algorithmus ist eng mit der eigentlichen Zeichnung verbunden.

+0

Frage Wesen "on hold": Man könnte die Frage umformulieren Beispiel-Code in Java von Kurvenanpassung Code zu geben (natürlich, dass Code in einigen Bibliotheken ziehen, so Das kann man als Empfehlung sehen). Bei dieser Frage geht es nicht um JFreeChart, das nur die Punkte übernimmt und sie anzeigt, aber keine zusätzlichen Punkte generiert. Ich bin wirklich erstaunt, dass Linked und Related genau diese Frage nicht zeigen. –

Antwort

0

Ich habe es nie getan, aber eine schnelle Google-Suche ergab, dass Bezier-Kurven in http://java.sun.com/j2se/1.5.0/docs/api/java/awt/geom/QuadCurve2D.Double.html

Dann implementiert sind, können Sie getPathIterator() aus dieser Kurve und damit, nach welcher Dokumentation sagt, Sie bekommen die "Koordinaten der Formgrenzen", die wohl das sind, wonach Sie suchen.

+1

Nein, er will das nicht machen. Er muss Kontrollpunkte der Kurve mit Spline-Interpolation oder einer Heuristik-Methode berechnen. – Matej

+0

Ich schlage vor, Sie lesen besser http://en.wikipedia.org/wiki/Spline_(mathematics) und http://en.wikipedia.org/wiki/B%C3%A9zier_curve Bezier-Kurven ist eine der Möglichkeiten zu modelliere diese Kurven. Indem er die Koordinaten von Punkten auf dieser Kurve hat, bekommt er effektiv, was er will. – jbasko

4

Apache Commons Math hat eine schöne Reihe von Algorithmen, insbesondere "SplineInterpolator", das API docs

Ein Beispiel sehen, wie wir die Interpolationsfunktionen für Alpha nennen (x), beta (x) von 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

Und jetzt ein Wegthema Beispiel für Fortschreibungen, weil es Spaß macht. Hier verwenden wir die gleichen Daten wie oben, extrapolieren aber mit einem Polynom zweiten Grades. Und die passenden Klassen natürlich. Wieder in 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