package com.singularsys.jepexamples.applets; import java.awt.*; import com.singularsys.jep.EvaluationException; import com.singularsys.jep.Jep; import com.singularsys.jep.ParseException; /** * This class plots a graph using the JEP API. */ public class GraphCanvas extends Canvas { private static final long serialVersionUID = -3169263228971794887L; /** Scaling of the graph in x and y directions */ private int scaleX, scaleY; /** Dimensions of the canvas */ private Dimension dimensions; /** Buffer for the graph */ private Image buffer; /** Boolean flags */ private boolean initializedBuffer, changedFunction, hasError; /** Math parser */ private Jep jep; /** The expression field where the functions are entered */ private java.awt.TextField exprField; /** * Constructor */ public GraphCanvas(String initialExpression, java.awt.TextField exprField_in) { scaleX = 1; scaleY = 1; dimensions = getSize(); initializedBuffer = false; changedFunction = true; hasError = true; exprField = exprField_in; initParser(initialExpression); } /** * Initializes the parser */ private void initParser(String initialExpression) { // Init Parser jep = new Jep(); // Allow implicit multiplication jep.setImplicitMul(true); // Add and initialize x to 0 jep.addVariable("x", 0); // Set the string to the initial value setExpressionString(initialExpression); } /** * Sets a new string to be used as function */ public void setExpressionString(String newString) { // Parse the new expression try { jep.parse(newString); exprField.setForeground(Color.black); hasError = false; } catch (ParseException e) { exprField.setForeground(Color.red); hasError = true; } changedFunction = true; } /** * @return The value of the function at an x value of the parameter. */ private double getYValue(double xValue) { // Save the new value in the symbol table jep.addVariable("x", xValue); try { Object result = jep.evaluate(); if (result instanceof Double) { return ((Double) jep.evaluate()).doubleValue(); } else { throw new EvaluationException("Non-Double result"); } } catch (EvaluationException e) { return 0; } } /** * Fills the background with white. */ private void paintWhite(Graphics g) { g.setColor(Color.white); g.fillRect(0,0,dimensions.width,dimensions.height); } /** * Paints the axes for the graph. */ private void paintAxes(Graphics g) { g.setColor(new Color(204,204,204)); g.drawLine(0,dimensions.height/2,dimensions.width-1,dimensions.height/2); g.drawLine(dimensions.width/2,0,dimensions.width/2,dimensions.height-1); } /** * Paints the graph of the function. */ private void paintCurve(Graphics2D g) { boolean firstpoint=true; int lastX=0, lastY=0; g.setColor(Color.black); for (int xAbsolute = 0; xAbsolute <= (dimensions.width-1); xAbsolute++) { double xRelative = (xAbsolute - dimensions.width/2)/scaleX; double yRelative = getYValue(xRelative); int yAbsolute = (int)(-yRelative*scaleY + dimensions.height/2); if (yAbsolute > dimensions.height) yAbsolute = dimensions.height; if (yAbsolute < -1) yAbsolute = -1; if (firstpoint != true) g.drawLine(lastX, lastY, xAbsolute, yAbsolute); else firstpoint = false; lastX = xAbsolute; lastY = yAbsolute; } } /** * Draws the graph to the Graphics object. If the image buffer has been * initialized, and the function has not changed since the last paint, * the image stored in the buffer is drawn straight to the Graphics * object with drawImage(). *
* If a image buffer has not yet been initialized (i.e. first time after * being started) the buffer is created with createImage(). *
* If the function has changed since the last paint, the graph is first * drawn on the buffer image, then that image is drawn on the Graphics * object. */ public void paint(Graphics g_in) { boolean changedDimensions = !dimensions.equals(getSize()); Graphics2D g = (Graphics2D) g_in; // If the buffer has not been initialized, do it now if (!initializedBuffer || changedDimensions) { dimensions = getSize(); buffer = createImage(dimensions.width,dimensions.height); initializedBuffer = true; } // Get the Graphics instance of the buffer Graphics2D buffergc = (Graphics2D) buffer.getGraphics(); // Turn on anti aliasing buffergc.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Redraw the function on the buffer if (changedFunction || changedDimensions) { paintWhite(buffergc); paintAxes(buffergc); if (!hasError) paintCurve(buffergc); changedFunction = false; } // Copy the buffer to g g.drawImage(buffer, 0, 0, null); } }