package gve.calc;

import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import gve.calc.formula.*;

public class Bernstein extends Applet implements ItemListener,Layer,ActionListener,Runnable {
	private PlotCanvas plotcan;
	private Choice funcChoice,graadChoice;
	
Bernstein polynomial takes values of f between xmin and xmax. Note: things go wrong when xmin!=0 or xmax!=1
private double xmin=0,xmax=1;
Values of the function at equidistant points between xmin and xmax
private double [] fvalues; private Label status; private Button animateButton; private boolean pleaseStop = false; public boolean isAnimating = false; public void init() { setLayout(new BorderLayout()); Panel p = new Panel(); p.add(new Label("Functie:")); Choice c; p.add(c = new Choice()); funcChoice = c; c.add("abs(2x-1)"); c.add("sin(pi*x)"); c.add("cos(pi*x)"); c.add("x^2"); c.add("x^3"); c.addItemListener(this); p.add(new Label("graad:")); p.add(c = new Choice()); graadChoice = c; for (int i = 1; i <= 15; i++) c.add(""+i); c.addItemListener(this); Button b; p.add(b = new Button("+")); b.addActionListener(this); p.add(b = new Button("-")); b.addActionListener(this); p.add(b = new Button("Anim")); b.addActionListener(this); animateButton = b; add("North",p); add("Center",plotcan = new PlotCanvas()); plotcan.setDbuffer(true); // plotcan.setPlotMode(PlotCanvas.INTERVALS); plotcan.setRanges(-1,2,-1,2); add("South",status = new Label("",Label.LEFT)); itemStateChanged(null); // create plot functions } public void actionPerformed(ActionEvent evt) { String cmd = evt.getActionCommand(); if (cmd.equals("Anim")) { new Thread(this).start(); } else if (cmd.equals("Stop")) { pleaseStop = true; } else if (cmd.equals("+")) { int graad = Integer.parseInt(graadChoice.getSelectedItem()); graadChoice.select(""+(graad+1)); itemStateChanged(null); } else if (cmd.equals("-")) { int graad = Integer.parseInt(graadChoice.getSelectedItem()); graadChoice.select(""+(graad-1)); itemStateChanged(null); } } public void sleep(int ms) { try { Thread.sleep(ms); } catch (InterruptedException exc) {} } public void run() { if (isAnimating) /* Don't animate twice */ return; animateButton.setLabel("Stop"); isAnimating = true; for (int graad = 1; graad <= 15; graad++) { if (pleaseStop) { pleaseStop = false; break; } graadChoice.select(""+graad); itemStateChanged(null); plotcan.repaint(10); // repaint in 10ms sleep(500); // wait for plot to start while (plotcan.isPlotting()) sleep(100); // wait for plot to finish if (!pleaseStop) sleep(1000); } isAnimating = false; animateButton.setLabel("Anim"); } public void itemStateChanged(ItemEvent evt) { int graad = Integer.parseInt(graadChoice.getSelectedItem()); fvalues = new double[graad+1]; double [] coeffs = new double[graad+1]; String fname = funcChoice.getSelectedItem(); Formula f = null; if (fname.equals("sin(pi*x)")) f = new Formula(new OperatorSpace(new Identifier("sin"),new OperatorMult(new Identifier("x"),new Identifier(""+Math.PI)))); else if (fname.equals("cos(pi*x)")) f = new Formula(new OperatorSpace(new Identifier("cos"),new OperatorMult(new Identifier("x"),new Identifier(""+Math.PI)))); else if (fname.equals("x^2")) f = new Formula(new OperatorPow(new Identifier("x"),new Identifier("2"))); else if (fname.equals("x^3")) f = new Formula(new OperatorPow(new Identifier("x"),new Identifier("3"))); else if (fname.equals("abs(2x-1)")) f = new Formula(new OperatorSpace(new Identifier("abs"), new OperatorMinus(new OperatorMult(new Identifier("2"),new Identifier("x")),new Identifier("1")) )); plotcan.setFunction(f); // Bernstein stuff Evaluator ev = new MultiEvaluator(); StandardFunctions.registerFunctions(ev); Real dv = new Real(0.0); ev.defineVariable("x",dv); double comb = 1; // = (n k) for (int k = 0; k <= graad; k++) { // voorfactor comb = (n k) berekenen if (k == 0) comb = 1; else comb = comb * (double)(graad-k+1) / (double)k; // functiewaarde dv.doubleValue = xmin + (double)k/graad*(xmax-xmin); Part res = f.evaluate(ev); double fx = 0; if (res instanceof Real) { fx = ((Real)res).doubleValue; } else return; fvalues[k] = fx; // Add comb * f(x) * x^k * (1-x)^(n-k) fx *= comb; // prefactor { double binom = 1; // coeff. for Newton's binomium for (int j = 0; j <= graad-k; j++) { if (j != 0) binom = -binom * (double)(graad-k-j+1) / (double)j; coeffs[j+k] += binom * fx; } } } Part bernstein = null; String txt = null; for (int i = 0; i <= graad; i++) { double c = coeffs[i]; // coefficient of the term x^i if (Math.abs(c) <= 1E-10) continue; Part term = null; Identifier id = new Identifier(""+c); String str; if (i==0) { term = id; str = ""+c; } else if (i==1) { term = new OperatorMult(id,new Identifier("x")); if (c == 1) str = "x"; else str = c+"x"; } else { term = new OperatorMult(id,new OperatorPow(new Identifier("x"),new Identifier(""+i))); if (c == 1) str = "x^"+i; else str = c+"x^"+i; } if (bernstein == null) bernstein = term; else bernstein = new OperatorPlus(bernstein,term); if (txt == null) txt = str; else txt += " + "+str; } if (bernstein == null) { bernstein = new Identifier("0"); txt = "0"; } status.setText(txt); f = new Formula(bernstein); plotcan.addFunction(f); plotcan.setLayer(this); } public void paintLayer(Graphics g,int width,int height) { // assenkruis int y = plotcan.yToPix(0); g.setColor(Color.blue); g.drawLine(0,y,width,y); int x = plotcan.xToPix(0); g.drawLine(x,0,x,height); x = plotcan.xToPix(1); g.drawLine(x,y-5,x,y+5); // x=1 tick x = plotcan.xToPix(0); y = plotcan.yToPix(1); g.drawLine(x-5,y,x+5,y); // y=1 tick g.setColor(Color.red); int graad = Integer.parseInt(graadChoice.getSelectedItem()); for (int k = 0; k <= graad; k++) { // NOTE: we suppose [xmin,xmax] = [0,1] ... x = plotcan.xToPix((double)k / (double)graad); y = plotcan.yToPix(fvalues[k]); // g.drawLine(x-5,y-5,x+5,y+5); // g.drawLine(x-5,y+5,x+5,y-5); g.fillOval(x-2,y-2,5,5); } } }