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

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;
}


	
}
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;
}
1

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

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