// Titel: PolyPlot v 1.1 applet // Datum: 26 november 1997 // 13 juni 1998 appletversie (AvD) // Auteurs: Arthur van Dam & Tijmen Collignon // // Beschrijving: Dit programma berekent en plot polynomen // door aangeklikte coordinaten mbv de 'LaGrange'-methode. // 27 juli 2001: cleaned up multi-language support - AvD import java.awt.*; import java.applet.Applet; import java.lang.*; import java.util.Hashtable; public class Polyplotp extends Applet { TextField formule, coordinates, punten; PolyCanv scherm; Polynoom p; Punt punt; Choice schaalkeuze; PolyplotLangSupport langSupport; public void init() { Panel knoppen, uitvoer; setBackground(Color.white); resize(510,450); langSupport = new PolyplotLangSupport(getParameter("lang")); punt = new Punt(); // punt object nu al aanmaken om mee te geven aan klasse Polynoom. p = new Polynoom(punt); knoppen = new Panel(); uitvoer = new Panel(); scherm = new PolyCanv(langSupport, p, punt, this); // Scherm heeft dezelfde Polynoom onder handen, dezelfde punt-object, // en moet TextFields in klass Frame kunnen aanpassen. punten = new TextField(); formule = new TextField(70); coordinates = new TextField(8); schaalkeuze = new Choice(); // Keuzelijst voor de schaal. schaalkeuze.addItem(" 1:1"); schaalkeuze.addItem(" 2:1"); schaalkeuze.addItem(" 5:1"); schaalkeuze.addItem("10:1"); schaalkeuze.addItem("25:1"); schaalkeuze.addItem("50:1"); schaalkeuze.select(3); formule. setText(langSupport.get("msg_welcome")); formule. setEditable(false); coordinates.setEditable(false); punten. setEditable(false); uitvoer.setLayout( new BorderLayout()); // Borderlayout wordt gebruikt voor goed inpassen TextFields. uitvoer.add("North", formule); uitvoer.add("East", coordinates); uitvoer.add("West", schaalkeuze); uitvoer.add("Center", punten); knoppen.setLayout(new GridLayout(2, 1, 0, 0)); knoppen.add(new Button(langSupport.get("cmd_clear"))); knoppen.add(new Button(langSupport.get("cmd_interpolate"))); GridBagLayout gbl = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); Panel total = new Panel(); total.setLayout(gbl); gbc.ipadx=1; gbl.setConstraints(knoppen, gbc); total.add(knoppen); gbc.fill=GridBagConstraints.HORIZONTAL; gbl.setConstraints(uitvoer, gbc); add(uitvoer); add("North", total); add("Center", scherm); } public boolean action(Event ev, Object obj) { String s; int n = schaalkeuze.getSelectedIndex(); try // Kijkt even of Button is ingedrukt, anders { s = ((Button)ev.target).getLabel(); } catch(ClassCastException e) { s = schaalkeuze.getSelectedItem(); // was het een Keuze Item. } if(s==langSupport.get("cmd_clear")) // Nu is de String bekend, dus alle mogelijkheden langslopen { p.Reset(); scherm.wissen(); } else if(s==langSupport.get("cmd_interpolate") && punt.aantal > 0) // Zonder punten niet tekenen { p.Reset(); // Arrays op nul p.Lagrange(); // Polynoom p opnieuw opstellen formule.setText("" + p); // Na berekening p, formule opstellen scherm.plotter = true; // Paint laten weten dat er getekend mag worden scherm.repaint(); } else{ switch(n){ case 0 : scherm.schaal = 1; break; case 1 : scherm.schaal = 2; break; case 2 : scherm.schaal = 5; break; case 3 : scherm.schaal = 10; break; case 4 : scherm.schaal = 25; break; case 5 : scherm.schaal = 50; break; } scherm.plotter = true; scherm.repaint(); } return true; } } class PolyCanv extends Canvas { Polyplotp plot; Polynoom p; Punt punt, plotpunt; // plotpunt: apart punt-object voor tekenen volledige polynoom final int x_midden = 255, y_midden = 200; // constanten voor midden van PolyCanv (en lokatie oorsprong) int schaal; boolean plotter; // Aan de hand hiervan weet Paint of hij naast de punten ook de Polynoom // mag tekenen PolyplotLangSupport langSupport; PolyCanv(PolyplotLangSupport langSupport, Polynoom huidigp, Punt huidigpunt, Polyplotp huidigplot) { resize(510,400); setBackground(new Color(195, 195, 195)); plotter = false; plot = huidigplot; p = huidigp; punt = huidigpunt; schaal = 10; this.langSupport = langSupport; repaint(); } public void paint(Graphics g) { Font schaalfont = new Font((getFont()).getName(), Font.PLAIN,10); g.setFont(schaalfont); g.drawLine(0, y_midden, 2*x_midden-1, y_midden); // Draw axes g.drawLine(x_midden, 0, x_midden, 2*y_midden-1); for(int h = x_midden%50; h<=(2*x_midden-1); h+=50) { g.drawLine(h, y_midden+3, h, y_midden-3); // Zet schaalverdeling met op schaal g.drawString(""+(h-x_midden)/schaal, h-10, y_midden+15); // aangepaste cijfers (x-as) } for(int v = y_midden%50; v<=(2*y_midden-1); v+=50) { g.drawLine(x_midden-3, v, x_midden+3, v); // idem voor y-as if(v != y_midden) g.drawString(""+(y_midden - v)/schaal, x_midden+5, v+5); } for(int i=0; i 0) g.drawLine((int)(schaal*(plotpunt.xs[xteller-1])) + x_midden, y_midden - (int)(schaal*plotpunt.ys[xteller-1]), (int)(schaal*plotpunt.xs[xteller]) + x_midden, y_midden - (int)(schaal*plotpunt.ys[xteller])); } plotter = false; } } public boolean mouseDown(Event evt, int x, int y) { if(punt.Checkpoint((double)(x - x_midden)/schaal)==false) plot.formule.setText(langSupport.get("msg_xexists")); else { // Voeg punt toe aan array, TextField en Canvas plot.formule.setText(langSupport.get("msg_nextpt")); punt.Voegtoe((double)(x - x_midden)/schaal, (double)(y_midden - y)/schaal); Font puntfont = new Font(getFont().getName(), Font.PLAIN, 12); plot.punten.setFont(puntfont); plot.punten.setText(langSupport.get("txt_pts") + ": " + punt); repaint(); } return true; } public boolean mouseMove(Event evt, int x, int y) // Laat coördinatenteller lopen tijdens bewegen { int xc = x - x_midden; int yc = y_midden - y; plot.coordinates.setText((double)xc/schaal + ", " + (double)yc/schaal); return true; } public boolean mouseExit(Event evt, int x, int y) { plot.coordinates.setText(""); return true; } public void wissen() { plot.formule.setText(langSupport.get("msg_ptscleared")); punt.Wissen(); try // Als wissen wordt ingedrukt voordat interpolate is ingedrukt, bestaat er *nog* geen plotpunt { plotpunt.Wissen(); plot.formule.setText(langSupport.get("msg_ptscleared")); } catch(Exception e) { plot.formule.setText(langSupport.get("msg_ptscleared")); } plot.punten.setText(langSupport.get("txt_pts") + ": " + punt); repaint(); } } class Punt { double xs[], ys[]; int aantal; Punt() { xs = new double[600]; // Als x_midden in PolyCanv wordt aangepast, dan hier ook arraylengte veranderen! ys = new double[600]; aantal = 0; } void Voegtoe(double x, double y) { xs[aantal] = x; ys[aantal] = y; aantal++; } boolean Checkpoint(double x) { for(int loper = 0; loper < aantal; loper++) if( xs[loper]== x ) return false; return true; } void Wissen() { for(int index = 0; index < aantal; index++) { xs[index]=0; ys[index]=0; } aantal = 0; } public String toString() // Geeft inhoud van array weer op TextField punten { String s = ""; if(aantal == 0) return ""; for(int loper = 0; loper < aantal; loper++) s += "["+ xs[loper] +", "+ ys[loper] +"], "; return s; } } class Polynoom { double coef[]; int graad; Punt punt; Polynoom(Punt huidigpunt) { coef = new double[100]; graad = -1; // -1 staat voor ongedefinieerd, 0 is niet handig, // want dat betekent horizontale lijn over x-as. punt = huidigpunt; } void Lagrange() { Polynoom q; coef[0] = punt.ys[0]; graad = 0; for(int telpunt = 1; telpunt < punt.aantal; telpunt++) // loop alle ingevoerde punten langs { q = new Polynoom(punt); q.coef[0] = 1; q.graad = 0; q.Maak(telpunt, this); // maak correctie polynoom t.o.v. vorig polynoom Telop(q); // tel deze op bij de definitieve polynoom } } void Maak(int telpunt, Polynoom vorigpoly) { double b, noemer; b = punt.ys[telpunt] - vorigpoly.Vul_x_in(punt.xs[telpunt]); // Verschil tussen y-waarde en x-waarde ingevuld in oude polynoom. noemer = Noemer(telpunt); for(int teller = 0; teller < telpunt; teller++) Maal_x_c(punt.xs[teller]); for(int index = 0; index <= graad; index++) // Eindresultaat: polynoom volgens: coef[index] *= (b/noemer); // q(x)=(b/{a[m]-a[1])·...·(a[m]-a[m-1])}·(x-a[1])·...·(x-a[m-1]) } void Telop(Polynoom anderpoly) { for(int index = 0; index <= Math.max(graad,anderpoly.graad); index++) //Langste array bepaalt lengte som-array coef[index] += anderpoly.coef[index]; graad = Math.max(graad, anderpoly.graad); } double Vul_x_in(double x) { double uitkomst = 0; double macht = 1; for(int teller = 0; teller<=graad; teller++) { uitkomst += coef[teller]*macht; macht *= x; // Iedere keer vermenigvuldigen met x, // zodat niet telkens volledig nieuwe macht nodig is } return uitkomst; } void Maal_x_c(double c) // Vermenigvuldigt bestaande array met (x-c) { for(int loper = graad; loper >= 0; loper--) coef[loper + 1] = (coef[loper + 1] * - c) + coef[loper]; graad++; coef[0] *= -c; } double Noemer(int laatste) // Berekent noemer: (x[m]-x[1])·...·(x[m]-x[m-1]) { double uitkomst = 1; for(int puntloper = 0; puntloper <= laatste-1; puntloper++) uitkomst *= (punt.xs[laatste]-punt.xs[puntloper]); return uitkomst; } public String toString() { String s = "f(x) = "; for(int i = graad; i >= 0; i--) { if(s != "" && coef[i] > 0 && i < graad) // Geen + voor eerste en na laatste term. s += "+ "; if(coef[i] != 0 && coef[i] != 1) // Als coëfficiënt geen 0 of 1 is, s += coef[i] + ""; // afbeelden if(coef[i] != 0 && coef[i] != 1 && i != 0) // Als er een coëfficiënt en x staat s += "·"; // vermenigvuldigteken ertussen: if(coef[i] != 0 && i > 0) // Geen x bij 0·x en x^0 s += "x"; if(coef[i] != 0 && i == 1) // Geen machtteken, maar wel een spatie s += " "; if(coef[i] != 0 && i >= 2) // Bij zinvolle term, ^ + macht plaatsen s += "^"+ i + " "; } return s; } void Reset() { for(int index = 0; index <=graad; index++) // Alles op nul: tegen later foutief doorrekenen coef[index] = 0; graad = -1; // Aangeven dat array 'leeg' is; niet geldig } } class PolyplotLangSupport { private String lang; private String default_lang; private Hashtable dictionaries; private Hashtable activeDict; public PolyplotLangSupport(String lang) { default_lang = "eng"; initDictionaries(); setLang(lang); } public void setLang(String lang) { try { activeDict = (Hashtable)dictionaries.get(lang); } catch(NullPointerException e) { activeDict = (Hashtable)dictionaries.get(default_lang); } } private void initDictionaries() { Hashtable eng = new Hashtable(); Hashtable dut = new Hashtable(); eng.put("msg_welcome", new String("Welcome to Poly Plot v. 1.1 !")); eng.put("cmd_clear", new String("clear")); eng.put("cmd_interpolate", new String("interpolate")); eng.put("txt_pts", new String("Points")); eng.put("msg_xexists", new String("This x-value already belongs to an other point! Try again!")); eng.put("msg_nextpt", new String("Click another point or push \"Interpolate\"!")); eng.put("msg_ptscleared", new String("All points cleared")); dut.put("msg_welcome", new String("Welkom bij Poly Plot v. 1.1 !")); dut.put("cmd_clear", new String("wissen")); dut.put("cmd_interpolate", new String("interpoleer")); dut.put("txt_pts", new String("Punten")); dut.put("msg_xexists", new String("Deze x-waarde hoort al bij een ander punt; klik ergens anders!")); dut.put("msg_nextpt", new String("Klik een nieuw punt aan of druk op \"Interpoleer\"!")); dut.put("msg_ptscleared", new String("Alle punten gewist!")); dictionaries = new Hashtable(); dictionaries.put("eng", eng); dictionaries.put("dut", dut); } public String get(String key) { String value = (String)activeDict.get(key); if(value == null) { value = ""; } return value; } public String[] getList(String key) { String value[] = (String[])activeDict.get(key); if(value == null) { value = new String[0]; } return value; } }