Tutorial :Java curve fitting library [closed]



Question:

I'm hoping to find a simple library that can take a series of 2 dimensional points and give me back a larger series of points that model the curve. Basically, I want to get the effect of curve fitting like this sample from JFreeChart:

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

The problem with JFreeChart is that the code does not provide this type of api. I even looked at the source and the algorithm is tightly coupled to the actual drawing.


Solution:1

Apache Commons Math has a nice series of algorithms, in particular "SplineInterpolator", see the API docs

An example in which we call the interpolation functions for alpha(x), beta(x) from 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

And now for an off-topic example for EXTRAPOLATIONS, because it's fun. Here we use the same data as above, but extrapolate using an 2nd-degree polynomial. And the appropriate classes, of course. Again, 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


Solution:2

I've never done it, but a quick Google search revealed that Bezier curves are implemented in http://java.sun.com/j2se/1.5.0/docs/api/java/awt/geom/QuadCurve2D.Double.html

Then, you can getPathIterator() from this curve and with that, according to what documentation says, you get the "coordinates of shape boundaries", which, i suppose, is what you are looking for.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »