2009-05-18 7 views
18

Spero di trovare una libreria semplice che possa prendere una serie di punti bidimensionali e restituirmi una serie più ampia di punti che modellano la curva. Fondamentalmente, io voglio ottenere l'effetto della curva di raccordo come questo campione dalla JFreeChart:Libreria raccordo curva Java

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

Il problema con JFreeChart è che il codice non prevede questo tipo di api. Ho anche guardato la fonte e l'algoritmo è strettamente associato al disegno reale.

+0

domanda che "in attesa": Si potrebbe riformulare la questione di dare esempio di codice in Java di Curva Codice raccordo (naturalmente, che il codice tirerà in alcune librerie, in modo lo si può vedere come una raccomandazione). Questa domanda non riguarda JFreeChart, che prende solo i punti e li visualizza, ma non genera punti aggiuntivi. Sono davvero sorpreso che Linked e Related non mostrino esattamente questa domanda. –

risposta

0

ho mai fatto, ma una rapida ricerca su Google ha rivelato che le curve di Bezier sono implementati in http://java.sun.com/j2se/1.5.0/docs/api/java/awt/geom/QuadCurve2D.Double.html

Quindi, è possibile getPathIterator() da questa curva e che, secondo quanto dice la documentazione, si ottiene le "coordinate dei confini della forma", che, suppongo, è ciò che stai cercando.

+1

No, non vuole farlo. Ha bisogno di calcolare i punti di controllo della curva usando l'interpolazione spline o qualche metodo euristico. – Matej

+0

Ti suggerisco di leggere meglio http://en.wikipedia.org/wiki/Spline_(mathematics) e http://en.wikipedia.org/wiki/B%C3%A9zier_curve Le curve di Bezier sono uno dei modi per modella queste curve. Avendo le coordinate dei punti su questa curva, ottiene in effetti ciò che vuole. – jbasko

4

Apache Commons Math ha una bella serie di algoritmi, in particolare "SplineInterpolator", vedere il API docs

Un esempio in cui noi chiamiamo le funzioni di interpolazione per alfa (x), beta (x) da 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

E ora un esempio off-topic per estrapolazioni, perché è divertente. Qui usiamo gli stessi dati di cui sopra, ma estrapoliamo usando un polinomio di 2 ° grado. E le lezioni appropriate, ovviamente. Anche in questo caso, 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