import java.applet.*; import javax.swing.*; import java.awt.geom.*; import java.awt.event.MouseEvent; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Point; import java.text.DecimalFormat; import edu.jsu.leathrum.mathlets.shared.*; public class Tangent extends AMathlet { private class GraphPanel extends AGraphPanel { private class GraphCanvas extends AGraphCanvas { GeneralPath funcPath = new GeneralPath(); public GraphCanvas(int initialWidth, int initialHeight) { super(initialWidth, initialHeight); } protected void drawFigure(Graphics2D g) { g.setPaint(Color.blue); g.draw(c.tr.createTransformedShape(funcPath)); drawTangent(g); } public void buildFigure() { double fvalue = 0.0; boolean connected = false; double del = c.trinv.transform(new Point2D.Double(1,0),null).getX() - c.trinv.transform(new Point2D.Double(0,0),null).getX(); funcPath = new GeneralPath(); for (double x = c.xmin; x < c.xmax+del; x += del) { fvalue = evaluatef(x); if (Double.isNaN(fvalue) || Double.isInfinite(fvalue) || (fvalue < c.ymin) || (fvalue > c.ymax)) connected = false; else { if (connected) funcPath.lineTo((float) x, (float) fvalue); else { funcPath.moveTo((float) x, (float) fvalue); connected = true; } } } } public void drawTangent(Graphics2D g) { double xvalue = getx(); double fvalue = evaluatef(xvalue); double fpvalue = evaluatefp(xvalue); final int TANLEN = 60; double sfpvalue = 0.0, m = 0.0, a1 = 0.0, a2 = 0.0; Point2D p2; p2 = c.tr.transform(new Point2D.Double(xvalue, fvalue),null); if ((fvalue > c.ymin) && (fvalue < c.ymax)) { g.setPaint(Color.green); g.draw(c.tr.createTransformedShape(new Line2D.Double(xvalue,0.0,xvalue,fvalue))); if (!(Double.isNaN(fpvalue)||Double.isInfinite(fpvalue))) { sfpvalue = fpvalue*(c.xmax-c.xmin)/(c.ymax-c.ymin); m = Math.sqrt(sfpvalue*sfpvalue+1); a1 = TANLEN/m; a2 = a1*sfpvalue; g.setPaint(Color.red); g.draw(new Line2D.Double(p2.getX()-a1,p2.getY()+a2,p2.getX()+a1,p2.getY()-a2)); } } } } GraphCanvas canvas; public GraphPanel () { canvas = new GraphCanvas(HEIGHT,WIDTH); initPanel(canvas); } public void mousePressed(MouseEvent e) { if (!zoomingIn && !zoomingOut) { setx(c.trinv.transform(new Point2D.Double(e.getX(),0),null).getX()); redraw(); } } // overrides public void mouseDragged(MouseEvent e) { super.mouseDragged(e); setx(c.trinv.transform(new Point2D.Double(e.getX(),0),null).getX()); redraw(); } // overrides } private class ParserInputSet extends AParserInputSet { public ParserInputSet(String namestr, int size) { super(namestr, size); } double x; protected void setVars(double[] v) { x = v[0]; } protected double getVar(int id) { switch (id) { case Parser.VARX: return x; default: return Double.NaN; } } } GraphPanel graph = new GraphPanel(); String fStart = "f(x)="; String fpStart = "f'(x)="; ParserInputSet fField = new ParserInputSet(fStart,25); ParserInputSet fpField = new ParserInputSet(fpStart,25); JButton compButton = new JButton("graph"); JButton clearButton = new JButton("clear"); DoubleInputSet xanswer = new DoubleInputSet("x=",7); FormattedFixedWidthLabel fanswer = new FormattedFixedWidthLabel(fStart,200); FormattedFixedWidthLabel fpanswer = new FormattedFixedWidthLabel(fpStart,200); Box b1, b2; public Tangent() { this.getContentPane().setBackground(Color.white); this.getContentPane().setLayout(new FlowLayout()); this.getContentPane().add(graph); b1 = new Box(BoxLayout.Y_AXIS); b1.add(fField); b1.add(fpField); b2 = new Box(BoxLayout.X_AXIS); b2.add(Box.createHorizontalGlue()); b2.add(compButton); compButton.setOpaque(false); b2.add(clearButton); clearButton.setOpaque(false); b2.add(Box.createHorizontalGlue()); b1.add(b2); b1.add(xanswer); b1.add(fanswer); b1.add(fpanswer); this.getContentPane().add(b1); } public void localinit() { AMathlet.getNumberFormat().setMaximumFractionDigits(10); setHandler("x",xanswer); setHandler("f",fField); setHandler("fp",fpField); registerInputSet(fField); registerInputSet(fpField); registerInputSet(xanswer); registerGraphButton(compButton); registerClearButton(clearButton); fStart = AMathlet.getProperty("fxeq"); fpStart = AMathlet.getProperty("fpxeq"); xanswer.setName(AMathlet.getProperty("xeq")); fField.setName(fStart); fpField.setName(fpStart); xanswer.setDefault(Double.NaN); graph.localinit(); } public void localclear() { // some local stuff to clean up on clear() operation fanswer.setText(fStart); fpanswer.setText(fpStart); } // overrides public void draw() { fField.setDirty(); fpField.setDirty(); graph.reapply(); showValues(); } public double evaluatef(double x) { return fField.evaluatef(x); } public double evaluatefp(double x) { return fpField.evaluatef(x); } public double getx() { return xanswer.getValue(); } public void showValues() { double x = getx(); if (Double.isInfinite(x) || Double.isNaN(x)) { fanswer.setText(fStart); fpanswer.setText(fpStart); } else { double fx = evaluatef(x); double fpx = evaluatefp(x); if (Double.isInfinite(fx) || Double.isNaN(fx)) fanswer.setText(fStart); else fanswer.setText(fStart+AMathlet.getNumberFormat().format(fx)); if (Double.isInfinite(fpx) || Double.isNaN(fpx)) fpanswer.setText(fpStart); else fpanswer.setText(fpStart+AMathlet.getNumberFormat().format(fpx)); } } public void setx(double x) { if (Double.isInfinite(x) || Double.isNaN(x)) xanswer.setToDefault(); else xanswer.setValue(x); showValues(); } }