Rysowanie wykresu interpolacji, błąd obliczania wartości.

Odpowiedz Nowy wątek
2015-02-04 09:55
0

Cześć, mam do napisania program rysujący wykres podanej funkcji oraz wykres interpolacji. Problem jest z tym że mam dużo punktów i gdy dochodzi do rysowania wykresu interpolacji wykres bardzo szybko "ucieka", ma to miejsce głównie dla funkcji trygonometryczny dla funkcji typu: x^2 działa dobrze, bardzo byłbym wdzięczny gdyby ktoś mógł zerknąć na kod i podpowiedzieć co może być źle :)

Problem wygląda mniej więcej tak (zielonym interpolacja, czerwonym podana funkcja):

RvMzfkX.png

do obliczania punktów korzystam z parsera JEP http://www.singularsys.com/jep/doc/html/functions.html

główny kod odpowiedzialny za rysowanie i obliczenia

 import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import org.jfree.data.xy.XYSeries;
import org.apache.commons.math3.analysis.polynomials.PolynomialFunctionLagrangeForm;

/**
 *
 * @author user
 */
public class Funrys {

    protected double OX, OY;//, f1, f2, d, dt;
        private BufferedImage Img;
        private TPaintPanel Panel;
        protected String wzor;
        protected List punkty;
        protected  List<Double> pointsX;
        protected  List<Double> pointsY;
        protected boolean czyInter;
        protected PolynomialFunctionLagrangeForm lagrange;

        public Funrys(TPaintPanel pp)
        {
            Panel = pp;
        }

    public void doSth() {
            Img = new BufferedImage(700, 480, BufferedImage.TYPE_INT_RGB);
            Graphics ig = Img.getGraphics();
            //setParams(1, 1, 9,8, Math.PI/2 , .01);
            paint((Graphics2D) ig);
            Panel.setSize(700, 480);
            Panel.AssignRys(Img);
            Panel.repaint();
            //setParams(5, 4, 3, 5, Math.PI/2, .01);

    }   
    public void setParams(double ox, double oy, String wzur, boolean inter) {
        OX = ox; 
                OY = oy; 
                wzor = wzur;
                czyInter = inter;

    }
    //rysowanie wykresu funkcji
    private void paint(Graphics2D g) {
        int w = 700, h = 480, hw = w/2, hh = h/2;
        //g.setFont(new Font("dialog", Font.PLAIN, 9));
        //FontMetrics fm = g.getFontMetrics();
        g.setColor(new Color(23, 128, 0));
        g.drawLine(0, hh, w, hh); //x os
        g.drawLine(hw, 0, hw, h); //y os
        g.drawString("x", w-10, hh-5); 
        g.drawString("y", hw-7, 10);

            //double sfact = min((hw-fm.stringWidth(Double.toString(-b))-6)/a, (hh-fm.getAscent()-6)/b);
                        double asfuck = min((hw-20)/OX, (hh-20)/OY);
                        int xmax = (int)(asfuck*OX), ymax = (int)(asfuck*OY);
            g.drawLine(hw-xmax, hh-ymax, hw+xmax, hh-ymax); //ramka
            g.drawLine(hw-xmax, hh+ymax, hw+xmax, hh+ymax); // jw
            g.drawLine(hw-xmax, hh-ymax, hw-xmax, hh+ymax); //jw
            g.drawLine(hw+xmax, hh-ymax, hw+xmax, hh+ymax); // jw
            //g.drawString(Double.toString(a), hw+xmax-fm.stringWidth(Double.toString(a))/2, hh+ymax+fm.getAscent()+3);
                        //g.drawString(Double.toString(-a), hw-xmax-fm.stringWidth(Double.toString(-a))/2, hh+ymax+fm.getAscent()+3);
            //g.drawString(Double.toString(b), hw-xmax-fm.stringWidth(Double.toString(b))-3, hh-ymax+fm.getAscent()/2-1);
            //g.drawString(Double.toString(-b), hw-xmax-fm.stringWidth(Double.toString(-b))-3, hh+ymax+fm.getAscent()/2-1);

                        g.drawString(Double.toString(OX), hw+xmax+2, hh);  //x
                        g.drawString(Double.toString(-OX), hw-xmax-24, hh); // -x
                        g.drawString(Double.toString(-OY), hw+10, hh+ymax+17); // -y
            g.drawString(Double.toString(OY), hw+10, hh-ymax-7); // y

                       g.setColor(new Color(240, 9, 9));

                      for(int i=1; i<=pointsX.size()-1; i++){

                           double pX, pY, pX2, pY2;

                            pX = pointsX.get(i-1)*asfuck;
                            pY = pointsY.get(i-1)*asfuck;

                            pX2=pointsX.get(i)*asfuck;
                            pY2=pointsY.get(i)*asfuck;

                           Shape l = new Line2D.Double(hw+pX, hh-pY, hw+pX2, hh-pY2);
                           g.draw(l);

                       }

      /*********************rysowanie interpolacji*************************************/
                      g.setColor(new Color(0, 255, 0));
                if(czyInter){

                    double inX[] = new double[pointsX.size()];
                    double inY[] = new double[pointsX.size()];
                    for(int i=0; i<=pointsX.size()-1; i++){
                        inX[i]=pointsX.get(i);
                        inY[i]=pointsY.get(i);

                    }

                       double interY[] = new double[pointsX.size()];
                       //obliczanie wartosc dla podanych X

                       for(int k=0; k<=(OX*2)/0.01; k++){

                          interY[k] = interpolacjaStopien(inX[k], 4, inX, inY);

                          System.out.println(inX[k]+"\t"+k+"\t"+interY[k]);

                       }

                         for(int i=1;  i<=inX.length-1; i++){   

                           double pX, pY, pX2, pY2;

                            pX = inX[i-1]*asfuck;
                            pY = interY[i-1]*asfuck;

                            pX2 = inX[i]*asfuck; 
                            pY2 = interY[i]*asfuck;

                           Shape l = new Line2D.Double(hw+pX, hh-pY, hw+pX2, hh-pY2);
                           g.draw(l);

                       }
                }

    }

    private static double min(double a, double b) { return (a < b) ? a : b; }

        public void getPoints(String wzor){

                org.nfunk.jep.JEP myParser = new org.nfunk.jep.JEP();
                myParser.addStandardFunctions();
                myParser.addStandardConstants();

               pointsX = new ArrayList<>();
               pointsY = new ArrayList<>();
               pointsX.clear();
               pointsY.clear();

                for(double x =(-OX); x<=OX; x+=0.01){

                    myParser.addVariable("x", x);

                    myParser.parseExpression(wzor);
                    double result = myParser.getValue();
                    pointsX.add(x);
                    pointsY.add(result);
                }   
        }

//metoda do interpolacji

public double interpolacjaStopien (double x, int STOPIEN, double tab_x[], double tab_f[]) {
  double wynik = 0.0, L;
  for (int i=0; i<STOPIEN; i++) {
    L = 1.0;
          for (int j=0; j<STOPIEN; j++) {
                  if (j != i)
                          L = L * (x - tab_x[j]) / (tab_x[i] - tab_x[j]);
          }
    wynik = wynik + tab_f[i]*L;
  }

  return wynik;
}

}
edytowany 2x, ostatnio: bogdans, 2015-02-04 10:12
!Wstawiaj kod w znaczniki &lt;code=java&gt;&lt;/code&gt; - bogdans 2015-02-04 10:13

Pozostało 580 znaków

2015-02-04 14:46
0

Nikt nie ma pojęcia, dlaczego ten wykres ucieka?

kod dla interpolacji

 public double interpolacjaStopien (double x, int STOPIEN, double tab_x[], double tab_f[]) {
  double wynik = 0.0, L;
  for (int i=0; i<STOPIEN; i++) {
    L = 1.0;
          for (int j=0; j<STOPIEN; j++) {
                  if (j != i)
                          L = L * (x - tab_x[j]) / (tab_x[i] - tab_x[j]);
          }
    wynik = wynik + tab_f[i]*L;
  }

  return wynik;
}

Pozostało 580 znaków

2015-02-11 18:54

Kod interpolacji jest jak najbardziej OK, ale jest to interpolacja wielomianem Lagrange'a, musisz używać akurat tej metody? Pytam, bo ta metoda jest o tyle nieszczęsna że przy niektórych funkcjach i dużej ilości węzłów pojawiają się tzw. oscylacje Rungego (podejrzewam, że takie zjawisko jest właśnie na Twoim screenie). Polecam splajny, unikniesz tego problemu. Możesz poczytać wykład z mojej uczelni, tam jest wszystko opisane: http://th-www.if.uj.edu.pl/zfs/gora/metnumwstep/wyklad06.pdf

edytowany 1x, ostatnio: KarpatQ, 2015-02-11 18:57

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0