2009-05-18 34 views
18

Tôi hy vọng sẽ tìm thấy một thư viện đơn giản có thể lấy một loạt các điểm 2 chiều và cho tôi quay lại một loạt các điểm lớn hơn mô hình đường cong. Về cơ bản, tôi muốn để có được những ảnh hưởng của đường cong phù hợp như mẫu này từ JFreeChart:Thư viện phù hợp với đường cong Java

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

Vấn đề với JFreeChart là mã không cung cấp loại api. Tôi thậm chí còn nhìn vào nguồn và thuật toán được kết hợp chặt chẽ với bản vẽ thực tế.

+0

Câu hỏi con người "giữ lại": Người ta có thể xây dựng lại và các câu hỏi để cho mã ví dụ trong Java mã Lắp đường cong (tất nhiên mã SẼ kéo trong một số thư viện, vì vậy người ta có thể thấy đó là một khuyến nghị). Câu hỏi này không phải về JFreeChart, mà chỉ TAKES các điểm và hiển thị chúng nhưng không tạo thêm điểm. Tôi thực sự ngạc nhiên rằng Linked và Related không cho thấy chính xác câu hỏi đó. –

Trả lời

0

Tôi chưa bao giờ làm được điều đó, nhưng tìm kiếm trên Google nhanh chóng tiết lộ rằng các đường cong Bezier được thực hiện trong http://java.sun.com/j2se/1.5.0/docs/api/java/awt/geom/QuadCurve2D.Double.html

Sau đó, bạn getPathIterator() từ đường cong này và với điều đó, có thể theo những gì tài liệu nói, bạn sẽ có được "tọa độ của ranh giới hình dạng", mà, tôi cho rằng, là những gì bạn đang tìm kiếm.

+1

Không, anh ta không muốn làm điều này. Ông cần tính toán các điểm kiểm soát của đường cong bằng cách sử dụng nội suy spline hoặc một số phương pháp heuristics. – Matej

+0

Tôi khuyên bạn nên đọc http://en.wikipedia.org/wiki/Spline_(mathematics) và http://en.wikipedia.org/wiki/B%C3%A9zier_curve Đường cong Bezier là một trong những cách để mô hình hóa các đường cong này. Bằng cách có các tọa độ của các điểm trên đường cong này, anh ta có được những gì anh ta muốn. – jbasko

4

Apache Commons Math có một loạt tốt đẹp của các thuật toán, đặc biệt là "SplineInterpolator", xem API docs

Một ví dụ trong đó chúng ta gọi là chức năng nội suy cho alpha (x), beta (x) từ 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

Và bây giờ cho một ví dụ off-topic cho phép ngoại suy, bởi vì nó là thú vị. Ở đây chúng ta sử dụng cùng một dữ liệu như trên, nhưng ngoại suy sử dụng đa thức bậc hai. Và tất nhiên là các lớp học thích hợp. Một lần nữa, trong 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

Các vấn đề liên quan