// Luke Rogers // ID: 9320530 // ME 498/599 Computer Graphics - M.A. Ganter // // Please note to use this program you will need WindowListener.class in the // same subdirectory (folder) as this code. // // Plots a function on the screen with input from the user // import java.io.*; import java.lang.Class; import java.lang.reflect.Method; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import WindowListener.*; import java.awt.Component.*; //import Evaluate.*; //************************************************************************** public class Function extends Frame { static Scrollbar sbXRange = new Scrollbar(); static Scrollbar sbYRange = new Scrollbar(); static TextField tfXOrigin = new TextField(); static TextField tfYOrigin = new TextField(); static TextField tfFunction = new TextField(); static TextField tfInfo = new TextField(); static Choice chCellSize = new Choice(); static Button buRedraw = new Button(); static Checkbox cbGrad = new Checkbox(); static Checkbox cbSolid = new Checkbox(); static CheckboxGroup cbGroup = new CheckboxGroup(); static int theFrameWidth; static int theFrameHeight; static double[][] theArray = new double[441][441]; static double theMax; static double theMin; static String name = "Evaluate"; public Function() { setLayout(null); sbXRange.setOrientation(Scrollbar.HORIZONTAL); sbXRange.setValues(100,10,0,1010); sbXRange.setBounds(110,60,100,30); sbXRange.setUnitIncrement(10); sbXRange.setBlockIncrement(10); add(sbXRange); sbYRange.setOrientation(Scrollbar.HORIZONTAL); sbYRange.setValues(100,10,0,1010); sbYRange.setBounds(220,60,100,30); sbYRange.setUnitIncrement(10); sbYRange.setBlockIncrement(10); add(sbYRange); tfXOrigin.setText("0"); tfXOrigin.setBounds(10,60,40,30); add(tfXOrigin); tfYOrigin.setText("0"); tfYOrigin.setBounds(60,60,40,30); add(tfYOrigin); tfFunction.setText(""); tfFunction.setBounds(10,27,310,30); add(tfFunction); tfInfo.setText(""); tfInfo.setBounds(10,95,440,30); add(tfInfo); chCellSize.add("1"); chCellSize.add("5"); chCellSize.add("10"); chCellSize.add("15"); chCellSize.add("20"); chCellSize.setBounds(330,20,50,50); chCellSize.select("10"); add(chCellSize); buRedraw.setLabel("Redraw"); buRedraw.setBounds(385,27,55,30); add(buRedraw); cbGrad.setLabel("Grad"); cbGrad.setCheckboxGroup(cbGroup); cbGrad.setState(true); cbGrad.setBounds(330,60,50,30); add(cbGrad); cbSolid.setLabel("Solid"); cbSolid.setCheckboxGroup(cbGroup); cbSolid.setState(false); cbSolid.setBounds(390,60,50,30); add(cbSolid); setTitle("A Function Plotter Application"); // Register Listners ChangeAction theAction = new ChangeAction(); AdjustmentAction theAdjustment = new AdjustmentAction(); MouseAction theMouseAction = new MouseAction(); ItemAction theItemAction = new ItemAction(); sbXRange.addAdjustmentListener(theAdjustment); sbXRange.addMouseListener(theMouseAction); sbYRange.addAdjustmentListener(theAdjustment); sbYRange.addMouseListener(theMouseAction); tfXOrigin.addActionListener(theAction); tfXOrigin.addMouseListener(theMouseAction); tfYOrigin.addActionListener(theAction); tfYOrigin.addMouseListener(theMouseAction); chCellSize.addItemListener(theItemAction); chCellSize.addMouseListener(theMouseAction); tfFunction.addActionListener(theAction); tfFunction.addMouseListener(theMouseAction); buRedraw.addActionListener(theAction); buRedraw.addMouseListener(theMouseAction); cbGrad.addItemListener(theItemAction); cbGrad.addMouseListener(theMouseAction); cbSolid.addItemListener(theItemAction); cbSolid.addMouseListener(theMouseAction); } //************************************************************************** // This is the paint method. It is called inside of the "show" method. public void paint(Graphics theGraphic) { // Cast into the graphics 2D world tfInfo.setText("Drawing the plot..."); //this.setProperties(); Graphics2D the2DGraphic = (Graphics2D) theGraphic; // Do loop to paint the plot i is the Y variable for (int i = 0; i < (theArray.length - 20); i = i + Integer.parseInt(chCellSize.getSelectedItem())) { // Do loop to paint the plot j is the X variable for (int j = 0; j < (theArray.length - 20); j = j + Integer.parseInt(chCellSize.getSelectedItem())) { // Create empty points for the gradient paint Point2D theMaxPoint = new Point2D.Double(); Point2D theMinPoint = new Point2D.Double(); int theMinShade = 0; int theMaxShade = 255; double theShadeScale = 255.0 / Math.abs(theMax - theMin); // Offsets to center the function graph double theXOffset = 25.0 - Integer.parseInt(chCellSize.getSelectedItem()); double theYOffset = 124.0 - Integer.parseInt(chCellSize.getSelectedItem()); // Set the rectangle width and height int theRectSize = Integer.parseInt(chCellSize.getSelectedItem()); // Set the rectangle x and y points double theRectX = (double)(j + theXOffset); double theRectY = (double)((theArray.length - 0 - i) + theYOffset); // Make copys of i and j for the out of bounds condition int ii = i; int jj = j; //if ((i + theRectSize) >= theArray.length) //ii = theArray.length - theRectSize - 1; //if ((j + theRectSize) >= theArray.length) //jj = theArray.length - theRectSize - 1; // Figure out the gradient shit if (cbGroup.getSelectedCheckbox() == cbGrad) { //get the values at the corners of the rect and their points double theUpperLeftValue = theArray[ii][jj]; Point2D theUpperLeftPoint = new Point2D.Double(theRectX, theRectY + theRectSize); int theUpperLeftShade = (int)((theArray[ii][jj] - theMin) * theShadeScale); double theUpperRightValue = theArray[ii][jj + theRectSize]; Point2D theUpperRightPoint = new Point2D.Double(theRectX + theRectSize, theRectY + theRectSize); int theUpperRightShade = (int)((theArray[ii][jj + theRectSize] - theMin) * theShadeScale); double theLowerLeftValue = theArray[ii + theRectSize][jj]; Point2D theLowerLeftPoint = new Point2D.Double(theRectX, theRectY); int theLowerLeftShade = (int)((theArray[ii + theRectSize][jj] - theMin) * theShadeScale); double theLowerRightValue = theArray[ii + theRectSize][jj + theRectSize]; Point2D theLowerRightPoint = new Point2D.Double(theRectX + theRectSize, theRectY); int theLowerRightShade = (int)((theArray[ii + theRectSize][jj + theRectSize] - theMin) * theShadeScale); //find the maximum value in the rect double max1 = Math.max(theUpperLeftValue, theUpperRightValue); double max2 = Math.max(theLowerLeftValue, theLowerRightValue); double max = Math.max(max1, max2); //find the minimum value in the rect double min1 = Math.min(theUpperLeftValue, theUpperRightValue); double min2 = Math.min(theLowerLeftValue, theLowerRightValue); double min = Math.min(min1, min2); // Figure out which damn points it is if (max == theUpperLeftValue) { theMaxPoint = theUpperLeftPoint; theMaxShade = theUpperLeftShade; } else if (max == theUpperRightValue) { theMaxPoint = theUpperRightPoint; theMaxShade = theUpperRightShade; } else if (max == theLowerLeftValue) { theMaxPoint = theLowerLeftPoint; theMaxShade = theLowerLeftShade; } else if (max == theLowerRightValue) { theMaxPoint = theLowerRightPoint; theMaxShade = theLowerRightShade; } if (min == theUpperLeftValue) { theMinPoint = theUpperLeftPoint; theMinShade = theUpperLeftShade; } else if (min == theUpperRightValue) { theMinPoint = theUpperRightPoint; theMinShade = theUpperRightShade; } else if (min == theLowerLeftValue) { theMinPoint = theLowerLeftPoint; theMinShade = theLowerLeftShade; } else if (min == theLowerRightValue) { theMinPoint = theLowerRightPoint; theMinShade = theLowerRightShade; } // create the colors Color theMinColor = new Color(theMinShade, theMinShade, theMinShade); Color theMaxColor = new Color(theMaxShade, theMaxShade, theMaxShade); //create a gradient between the max and min GradientPaint theGradient = new GradientPaint(theMinPoint, theMinColor, theMaxPoint, theMaxColor); Rectangle2D theRect = new Rectangle2D.Double(theRectX, theRectY, theRectSize, theRectSize); the2DGraphic.setPaint(theGradient); the2DGraphic.fill(theRect); } else // Must want to draw solid rectangles { int theShade = (int)((theArray[i][j] - theMin) * theShadeScale); Color theColor = new Color(theShade, theShade, theShade); Rectangle2D theRect = new Rectangle2D.Double(theRectX, theRectY, theRectSize, theRectSize); the2DGraphic.setPaint(theColor); the2DGraphic.fill(theRect); } } } tfInfo.setText(""); } //************************************************************************** public double[][] fillArray(int theSize, int theXOrigin, int theYOrigin, double theXRange, double theYRange) { //double[][] theArray = new double[theSize + 1][theSize + 1]; //Class theClassName = Evaluate.class; Class theEvalClass = Function.class; String theMethodName = "getAns"; // Initialize the YStep increment variable double theYStep = theYRange / theSize; // Initialize Y at its minimum value double Y = theYOrigin - (theYRange / 2); // Dynamically load the class tfInfo.setText("Populating the array..."); try { theEvalClass = Class.forName(name); } catch (ClassNotFoundException e) { tfInfo.setText("Class not found"); } Method theMethods[] = theEvalClass.getMethods(); //System.out.println(""+theMethods[0]); //theClassName = theMethods[0].getDeclaringClass(); //theMethodName = ""+theMethods[0].getName(); //System.out.println(""+theClassName); //System.out.println(""+theMethodName); for (int i = 0; i < theArray.length; i++) { // Initialize the XStep increment variable double theXStep = theXRange / theSize; // Initialize X at its minimum value double X = theXOrigin - (theXRange / 2); for (int j = 0; j < theArray.length; j++) { //Populate the Array // Call the Evaluate.class function getAns Object EvalArgs[] = new Object[1]; double d[] = new double[2]; EvalArgs[0] = d; d[0] = X; d[1] = Y; //theArray[i][j] = Evaluate.getAns(d); try { theArray[i][j] = ((Double)theMethods[0].invoke(theMethods[0],EvalArgs)).doubleValue(); } catch (IllegalAccessException e) { tfInfo.setText("IllegalAccessException"); } catch (java.lang.reflect.InvocationTargetException e) { tfInfo.setText("InvocationTargetException"); } catch (IllegalArgumentException e) { tfInfo.setText("IllegalArgumentException"); } // Increment the X variable X = X + theXStep; } // Increment the Y variable Y = Y + theYStep; } return theArray; } //************************************************************************** public double getMax(double[][] theArray) { double theMax = -99999999999999999999999999999999999999999999999999999.9; for (int i = 0; i < theArray.length; i++) { for (int j = 0; j < theArray.length; j++) { if (theArray[i][j] > theMax) theMax = theArray[i][j]; } } return theMax; } //************************************************************************** public double getMin(double[][] theArray) { double theMin = 999999999999999999999999999999999999999999999999999999.9; for (int i = 0; i < theArray.length; i++) { for (int j = 0; j < theArray.length; j++) { if (theArray[i][j] < theMin) theMin = theArray[i][j]; } } return theMin; } //************************************************************************** public void setProperties() { // Get the screen size Dimension theScreenDimensions = Toolkit.getDefaultToolkit().getScreenSize(); // set the frame's size //theFrameWidth = theScreenDimensions.width; //theFrameHeight = theScreenDimensions.height; //Or set the frame dimensions using integers int theFrameWidth = 460; int theFrameHeight = 580; this.setSize(theFrameWidth, theFrameHeight); this.setLocation(theScreenDimensions.width/2 - theFrameWidth/2, theScreenDimensions.height/2 - theFrameHeight/2); this.setResizable(false); this.setBackground(Color.white); } //************************************************************************** //************************************************************************** static public void main(String args[]) { WindowListener theWindowListener = new WindowListener(); Function theFunction = new Function(); // Add the window close capability to the Canvas theFunction.addWindowListener(theWindowListener); // Evaluate the fuction and create an array theFunction.writeFunction("x * x + y * y - 1"); tfFunction.setText("x * x + y * y - 1"); double[][] theArray = theFunction.fillArray(440, Integer.parseInt(tfXOrigin.getText()), Integer.parseInt(tfYOrigin.getText()), sbXRange.getValue(), sbYRange.getValue()); theMax = theFunction.getMax(theArray); theMin = theFunction.getMin(theArray); theFunction.setProperties(); theFunction.setVisible(true); } //************************************************************************** //************************************************************************** class MouseAction extends java.awt.event.MouseAdapter { public void mouseEntered(java.awt.event.MouseEvent event) { Object theObject = event.getSource(); if (theObject == sbXRange) sbXRange_MouseOn(event); else if (theObject == sbYRange) sbYRange_MouseOn(event); else if (theObject == tfXOrigin) tfXOrigin_MouseOn(event); else if (theObject == tfYOrigin) tfYOrigin_MouseOn(event); else if (theObject == chCellSize) chCellSize_MouseOn(event); else if (theObject == tfFunction) tfFunction_MouseOn(event); else if (theObject == buRedraw) buRedraw_MouseOn(event); else if (theObject == cbGrad) cbGrad_MouseOn(event); else if (theObject == cbSolid) cbSolid_MouseOn(event); } public void mouseExited(java.awt.event.MouseEvent event) { Object theObject = event.getSource(); if (theObject == sbXRange) feature_MouseOff(event); else if (theObject == sbYRange) feature_MouseOff(event); else if (theObject == tfXOrigin) feature_MouseOff(event); else if (theObject == tfYOrigin) feature_MouseOff(event); else if (theObject == chCellSize) feature_MouseOff(event); else if (theObject == tfFunction) feature_MouseOff(event); else if (theObject == buRedraw) feature_MouseOff(event); else if (theObject == cbGrad) feature_MouseOff(event); else if (theObject == cbSolid) feature_MouseOff(event); } } //************************************************************************** class ChangeAction implements java.awt.event.ActionListener { public void actionPerformed(java.awt.event.ActionEvent event) { Object theObject = event.getSource(); if (theObject == tfXOrigin) tfXOrigin_ActionPerformed(event); else if (theObject == tfYOrigin) tfYOrigin_ActionPerformed(event); else if (theObject == tfFunction) tfFunction_ActionPerformed(event); else if (theObject == buRedraw) buRedraw_ActionPerformed(event); } } //************************************************************************** class AdjustmentAction implements java.awt.event.AdjustmentListener { public void adjustmentValueChanged(java.awt.event.AdjustmentEvent event) { Object theObject = event.getSource(); if (theObject == sbXRange) sbXRange_AdjustmentPerformed(event); else if (theObject == sbYRange) sbYRange_AdjustmentPerformed(event); } } //************************************************************************** class ItemAction implements java.awt.event.ItemListener { public void itemStateChanged(java.awt.event.ItemEvent event) { Object theObject = event.getSource(); if (theObject == chCellSize) chCellSize_ItemChanged(event); else if (theObject == cbGrad) cbGrad_ItemChanged(event); else if (theObject == cbSolid) cbSolid_ItemChanged(event); } } //************************************************************************** void sbXRange_MouseOn(java.awt.event.MouseEvent event) { tfInfo.setText("Adjusts the X range"); } void sbYRange_MouseOn(java.awt.event.MouseEvent event) { tfInfo.setText("Adjusts the Y range"); } void tfXOrigin_MouseOn(java.awt.event.MouseEvent event) { tfInfo.setText("Sets the X origin"); } void tfYOrigin_MouseOn(java.awt.event.MouseEvent event) { tfInfo.setText("Sets the Y origin"); } void chCellSize_MouseOn(java.awt.event.MouseEvent event) { tfInfo.setText("Sets cell size from 1 x 1 to 20 x 20 pixels"); } void tfFunction_MouseOn(java.awt.event.MouseEvent event) { tfInfo.setText("Enter function here"); } void buRedraw_MouseOn(java.awt.event.MouseEvent event) { tfInfo.setText("Redraws the Function Graph"); } void cbGrad_MouseOn(java.awt.event.MouseEvent event) { tfInfo.setText("Fill cells with a gradient color"); } void cbSolid_MouseOn(java.awt.event.MouseEvent event) { tfInfo.setText("Fill cells with a solid color"); } void feature_MouseOff(java.awt.event.MouseEvent event) { tfInfo.setText(""); } void sbXRange_AdjustmentPerformed(java.awt.event.AdjustmentEvent event) { int theXRange = sbXRange.getValue(); int theXOrigin = Integer.parseInt(tfXOrigin.getText()); int theXMin = theXOrigin - (theXRange / 2); int theXMax = theXOrigin + (theXRange / 2); tfInfo.setText("Changing X Range to: "+theXMin+" to "+theXMax); } void sbYRange_AdjustmentPerformed(java.awt.event.AdjustmentEvent event) { int theYRange = sbYRange.getValue(); int theYOrigin = Integer.parseInt(tfYOrigin.getText()); int theYMin = theYOrigin - (theYRange / 2); int theYMax = theYOrigin + (theYRange / 2); tfInfo.setText("Changing Y Range to: "+theYMin+" to "+theYMax); } void tfXOrigin_ActionPerformed(java.awt.event.ActionEvent event) { try { int theXOrigin = Integer.parseInt(tfXOrigin.getText()); tfInfo.setText("Changing the X Origin to: "+theXOrigin); } catch (NumberFormatException e) { tfInfo.setText("Not a valid integer!"); tfXOrigin.setText("0"); } } void tfYOrigin_ActionPerformed(java.awt.event.ActionEvent event) { try { int theYOrigin = Integer.parseInt(tfYOrigin.getText()); tfInfo.setText("Changing the Y Origin to: "+theYOrigin); } catch (NumberFormatException e) { tfInfo.setText("Not a valid integer!"); tfYOrigin.setText("0"); } } void chCellSize_ItemChanged(java.awt.event.ItemEvent event) { int theCellSize = Integer.parseInt(chCellSize.getSelectedItem()); tfInfo.setText("Changing the cell size to: "+theCellSize); } void cbGrad_ItemChanged(java.awt.event.ItemEvent event) { tfInfo.setText("Changing color scheme to Gradient"); } void cbSolid_ItemChanged(java.awt.event.ItemEvent event) { tfInfo.setText("Changing color scheme to solid"); } void tfFunction_ActionPerformed(java.awt.event.ActionEvent event) { String theFunction = tfFunction.getText(); writeFunction(theFunction); } void buRedraw_ActionPerformed(java.awt.event.ActionEvent event) { theArray = this.fillArray(440, Integer.parseInt(tfXOrigin.getText()), Integer.parseInt(tfYOrigin.getText()), sbXRange.getValue(), sbYRange.getValue()); theMax = this.getMax(theArray); theMin = this.getMin(theArray); this.repaint(); } //*************************************************************************** public void writeFunction(String theFunction) { String unique; unique = ""+Math.round(Math.round(Math.random() * 1000)); name = "Evaluate"+unique; // this is where it will grab the string or it will be passed String expression = theFunction; try { // open an output file and connect it to a printwriter PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(name+".java"))); out.println(""); out.println("public class "+name+" {"); out.println(" public static double getAns ( double arg[]) {" ); out.println(" double x = arg[0];"); out.println(" double y = arg[1];"); out.println(" return ("+theFunction+");"); out.println(" }"); out.println("}"); out.close(); } catch (IOException e) { System.out.println("IOE : the stack trace is:"); e.printStackTrace(); } // Start the dynamic compile / load process // Check for class file and delete it File classFile = new File( name+".class" ); if ( classFile.exists()) { classFile.delete(); } // Compile tfInfo.setText("Compiling..."); String[ ] compile = { "javac", name+".java" }; try { Runtime.getRuntime( ).exec( compile ); } catch (IOException e) { tfInfo.setText("IOE in the compile"); } // Wait for the compile to happen int count = 100; while ( (!classFile.exists()) && (count > 0) ) { classFile = new File( name+".class" ); try { Thread.sleep( 200 ); count--; } catch (InterruptedException e) { tfInfo.setText("IntEx in the sleep"); } if (count <= 0) tfInfo.setText("Compiler Errors!!!"); } // Dynamically load the class file tfInfo.setText("Loading..."); try { // set up argument list Object funk_args[] = new Object[1]; double d[]= new double[2]; funk_args[0]=d; Double Z; double z; // dynamically load class Test.class which we just compiled Class C = Class.forName(name); // get the classes methods Method M[] = C.getMethods(); // set the arguments d[0] = 3.0; d[1] = 1.0 ; // call the function Z = (Double)M[0].invoke(M[0],funk_args); z = Z.doubleValue(); //System.out.println("Func("+d[0]+","+d[1]+")="+z); tfInfo.setText("Compile successful. Select Redraw to see plot."); } catch (IllegalAccessException e) { tfInfo.setText("I A E"); } catch (java.lang.reflect.InvocationTargetException e) { tfInfo.setText("I T E"); } catch (ClassNotFoundException e) { tfInfo.setText("Class not found. Illegal mathematical function?"); } // Check for class file and delete it File theClassFile = new File( name+".class" ); if ( theClassFile.exists()) { theClassFile.delete(); } // Check for java file and delete it File theJavaFile = new File( name+".java" ); if ( theJavaFile.exists()) { theJavaFile.delete(); } } }