/* @(#)FunctionsAndPlots.java 13 September 2006 */ /* Useful imports */ import edu.neu.ccs.*; import edu.neu.ccs.gui.*; import edu.neu.ccs.codec.*; import edu.neu.ccs.console.*; import edu.neu.ccs.filter.*; import edu.neu.ccs.jpf.*; import edu.neu.ccs.parser.*; import edu.neu.ccs.pedagogy.*; import edu.neu.ccs.quick.*; import edu.neu.ccs.util.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.awt.font.*; import java.awt.image.*; import javax.swing.*; import javax.swing.border.*; import java.io.*; import java.util.*; import java.math.*; import java.beans.*; import java.lang.reflect.*; import java.net.URL; import java.util.regex.*; import java.text.ParseException; /** * Class FunctionsAndPlots collects test methods that * evaluate expressions, define functions, and plot * functions. */ public class FunctionsAndPlots extends JPF { public static void main(String[] args) { // LookAndFeelTools.showSelectLookAndFeelDialog(); LookAndFeelTools.adjustAllDefaultFontSizes(4); new FunctionsAndPlots(); } /** * The parser that will be used to evaluate functions * for the purpose of making plots. */ BaseParser parser = ParserUtilities.getDefaultParser(); // A series of sample function objects to illustrate // how to define SimpleFunction objects in code SimpleFunction square = new SimpleFunction ("square", "x", "x^2"); SimpleFunction cube = new SimpleFunction ("cube", "x", "x^3"); SimpleFunction cuberoot = new SimpleFunction ("cuberoot", "x", "root(x,3)"); SimpleFunction fourth = new SimpleFunction ("fourth", "x", "x^4"); SimpleFunction fourthroot = new SimpleFunction ("fourthroot", "x", "root(x,4)"); /** * This method will lead to a GUI button that opens up a panel * in which the double input x may be entered as an expression * that is then evaluated and returned. * * This is the easiest way to take advantage of the built-in * JPT expression parser. */ public double Evaluate(double x) { return x; } /** * This method will permit the user to evaluate one or more * double expressions in the console window. * * The user can stop the process by pressing return after the * prompt message. */ public void EvaluateInConsole() { while (true) { try { console.out.println (console.in.requestDouble("Enter Double")); console.out.println(); } catch (CancelledException ce) { break; } } console.out.println(); } /** * This method brings up the JPT expression evaluation pane * that permits evaluation of expressions to type BigInteger, * double, or boolean. */ public void ExpressionEvaluationPane() { ExpressionEvaluationPane.main(null); } /** * This method brings up the JPT pane that manages the * definition of SimpleFunction objects. * * A SimpleFunction is defined by 3 strings: its name, * its comma-separated list of parameters, and its body. */ public void SimpleFunctionPane() { SimpleFunctionPane.main(null); } /** * This method brings up the JPT pane that manages the * definition of SimpleFunction objects and permits the * definitions to be saved to disk and read from disk. * * A SimpleFunction is defined by 3 strings: its name, * its comma-separated list of parameters, and its body. */ public void SimpleFunctionPaneWithIO() { SimpleFunctionPaneWithIO.main(null); } /** * The method brings up a pane that combines * a simple function definition pane * and an expression evaluation pane. */ public void SimpleFunctionBuilder() { SimpleFunctionBuilder.main(null); } /** * The method brings up a pane that combines * a simple function definition pane with IO * and an expression evaluation pane. */ public void SimpleFunctionBuilderWithIO() { SimpleFunctionBuilderWithIO.main(null); } /** * Plots one or more functions installed in the JPT parser. * These functions can be built-in functions or can be * user defined SimpleFunction objects. * * The functions are provided by giving a comma-separated * list of function names. * * The plot interval is from xMin to xMax. * * The variable steps is the number of subdivisions of the * plot interval. Since endpoints are plotted, there will * be (steps+1) plot points for each function. */ public void PlotTest (String functionNames, double xMin, double xMax, int steps) { // Call on the JPT parser to build a 2-dimensional table of // values for the functions provided. // Show an error dialog if an error occurs. Point2D[][] data = null; try { data = parser.makeTable(functionNames, xMin, xMax, steps); } catch (ParseException pe) { GeneralDialog.showOKDialog (pe.getMessage(), "Function Error"); return; } if ((data == null) || (data.length == 0)) { GeneralDialog.showOKDialog ("No function names", "Function Error"); return; } // Pass on the plot task to a helper method. PlotData(data, xMin, xMax, steps); } /** * Read in a polynomial function object and plot it. * * The plot interval is from xMin to xMax. * * The variable steps is the number of subdivisions of the * plot interval. Since endpoints are plotted, there will * be (steps+1) plot points for the function. */ public void PlotPolynomial (XPolynomial fcn, double xMin, double xMax, int steps) { // Pass on the plot task to a helper method. PlotFunction(fcn, xMin, xMax, steps); } /** * Read in a fourier series function object and plot it. * * The plot interval is from xMin to xMax. * * The variable steps is the number of subdivisions of the * plot interval. Since endpoints are plotted, there will * be (steps+1) plot points for the function. */ public void PlotFourierSeries (XFourier fcn, double xMin, double xMax, int steps) { // Pass on the plot task to a helper method. PlotFunction(fcn, xMin, xMax, steps); } /** * Plot a function object that implements Function.OneArg. * * The plot interval is from xMin to xMax. * * The variable steps is the number of subdivisions of the * plot interval. Since endpoints are plotted, there will * be (steps+1) plot points for the function. */ public void PlotFunction (Function.OneArg fcn, double xMin, double xMax, int steps) { if (fcn == null) return; // Use the DataTables2D class to make the table of values Point2D[] data = DataTables2D.makeTable(fcn, xMin, xMax, steps); // Pass on the plot task to a helper method. PlotData(data, xMin, xMax, steps); } /** * Plot a 1-dimensional data array as a single function. * * Scale the plot based on the data values. */ public void PlotData (Point2D[] data, double xMin, double xMax, int steps) { if ((data == null) || (data.length == 0)) { GeneralDialog.showOKDialog ("No plot data", "Plot Error"); return; } // Prepare the graphics window window.clearPanelAndSequence(); Graphics2D g = window.getBufferGraphics(); // Image bounds double w = window.getWidth(); double h = window.getHeight(); Rectangle2D image = new XRect(0, 0, w, h); // Use the data to find the world bounds for the plot PlotTool plot = new PlotTool(); Rectangle2D world = PlotTool.makeBoundsRectangle2D(data); world.add(0, 0); plot.setWorldBounds(world); plot.setImageBounds(image); plot.setInset(10); Stroke stroke = new BasicStroke(2); // Plot plot.autoTickMarks(g); plot.autoGridLines(g); plot.autoAxes(g); plot.plotData(g, data, Colors.red, stroke); // Repaint the graphics window window.repaint(); } /** * Plot a 2-dimensional data array as multiple functions. * * Scale the plot based on the data values. */ public void PlotData (Point2D[][] data, double xMin, double xMax, int steps) { if ((data == null) || (data.length == 0)) { GeneralDialog.showOKDialog ("No plot data", "Plot Error"); return; } // Prepare the graphics window window.clearPanelAndSequence(); Graphics2D g = window.getBufferGraphics(); // Image bounds double w = window.getWidth(); double h = window.getHeight(); Rectangle2D image = new XRect(0, 0, w, h); // Use the data to find the world bounds for the plot PlotTool plot = new PlotTool(); Rectangle2D world = PlotTool.makeBoundsRectangle2D(data); world.add(0, 0); plot.setWorldBounds(world); plot.setImageBounds(image); plot.setInset(10); Stroke stroke = new BasicStroke(2); // Plot plot.autoTickMarks(g); plot.autoGridLines(g); plot.autoAxes(g); plot.plotData(g, data, Colors.red, stroke); // Repaint the graphics window window.repaint(); } }