Subversion Repositories wimsdev

Rev

Blame | Last modification | View Log | RSS feed

  1. /*************************************************************************
  2. *                                                                        *
  3. *  This source code file, and compiled classes derived from it, can      *
  4. *  be used and distributed without restriction, including for commercial *
  5. *  use.  (Attribution is not required but is appreciated.)               *
  6. *                                                                        *
  7. *   David J. Eck                                                         *
  8. *   Department of Mathematics and Computer Science                       *
  9. *   Hobart and William Smith Colleges                                    *
  10. *   Geneva, New York 14456,   USA                                        *
  11. *   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
  12. *                                                                        *
  13. *************************************************************************/
  14.  
  15.  
  16. // The SimpleGraph applet is a configurable applet that displays the graph of
  17. // a single function of one variable and computes a Riemann sum for that
  18. // function.
  19.  
  20. import java.awt.*;
  21. import java.awt.event.*;
  22. import java.applet.Applet;
  23. import java.util.StringTokenizer;
  24. import edu.hws.jcm.draw.*;
  25. import edu.hws.jcm.data.*;
  26. import edu.hws.jcm.functions.*;
  27. import edu.hws.jcm.awt.*;
  28.  
  29.  
  30. public class RiemannSums extends GenericGraphApplet {
  31.  
  32.    // Declare some private variables that are created in one method in
  33.    // this class and used in a second method.
  34.  
  35.    private Variable intervals;       // Gives the number of intervals.
  36.    private VariableInput intCtInput; // For letting the user enter the number of intervals.
  37.    private Choice methodChoice;      // Gives the method to be used:  Left Endpoint, ..., Trapezoid.
  38.  
  39.    private Function func;   // The function that is graphed.
  40.    private Graph1D graph;   // The graph of the function.
  41.    
  42.    private RiemannSumRects sums;
  43.  
  44.    public void itemStateChanged(ItemEvent evt) {
  45.          // React when user changes the summation method.
  46.        if (evt.getSource() == methodChoice) {
  47.           sums.setMethod(methodChoice.getSelectedIndex());
  48.           mainController.compute();
  49.        }
  50.        else
  51.           super.itemStateChanged(evt);
  52.    }
  53.    
  54.    protected void setUpParameterDefaults() { // Override to give a different default function
  55.       parameterDefaults = new java.util.Hashtable();
  56.       String func = " 3 / (1 + " + getParameter("Variable","x") + "^2)";
  57.       parameterDefaults.put("Function",func);
  58.       parameterDefaults.put("ComputeButtonName","Compute!");
  59.    }
  60.  
  61.    protected void setUpCanvas() {  // Override this to add more stuff to the canvas.
  62.    
  63.       // When setUpCanvas is called, the functionInput already exists, if one is
  64.       // to be used, since it is created in setUpBopttomPanel(), which is called
  65.       // before setUpCanvas.  If functionInput exists, add a graph of the function
  66.       // from functionInput to the canvas.  If not, create a graph of the function
  67.       // specified by the parameter named "Function".
  68.      
  69.       if (functionInput != null)
  70.          func = functionInput.getFunction(xVar);
  71.       else {
  72.          String def = getParameter("Function", " abs(" + xVar.getName() + ") ^ " + xVar.getName());
  73.          Function f = new SimpleFunction( parser.parse(def), xVar );
  74.          func = new WrapperFunction(f);
  75.       }
  76.       graph = new Graph1D(func);
  77.       Color color = getColorParam("GraphColor");
  78.       if (color != null)
  79.          graph.setColor(color);
  80.          
  81.       // Get the data for the RiemannSumRects object.  Create it (along with other
  82.       // associated objects) and add it to the canvas.
  83.          
  84.       double[] intCtD = getNumericParam("IntervalCount");
  85.       if (intCtD == null || intCtD.length < 1)
  86.          intCtD = new double[] { 5 };
  87.       else if (Double.isNaN(intCtD[0]) || intCtD[0] < 1 || intCtD[0] > 5000)
  88.          intCtD[0] = 5;
  89.       int intCt = (int)(intCtD[0]+0.5);
  90.      
  91.       if ("yes".equalsIgnoreCase( getParameter("UseIntervalInput", "yes") )){
  92.          intCtInput = new VariableInput(null, "" + intCt);
  93.          intCtInput.setInputStyle(VariableInput.INTEGER);
  94.          intCtInput.setMin(1);
  95.          intCtInput.setMax(5000);
  96.          intervals = intCtInput.getVariable();
  97.       }
  98.       else
  99.          intervals = new Variable(null,intCt);
  100.      
  101.       int method = RiemannSumRects.LEFTENDPOINT;
  102.  
  103.       String methodStr = getParameter("Method");
  104.       if (methodStr != null && methodStr.trim().length() > 0) {
  105.          switch (methodStr.trim().charAt(0)) {
  106.             case 'L': case 'l': method = RiemannSumRects.LEFTENDPOINT; break;
  107.             case 'R': case 'r': method = RiemannSumRects.RIGHTENDPOINT; break;
  108.             case 'M': case 'm': method = RiemannSumRects.MIDPOINT; break;
  109.             case 'C': case 'c': method = RiemannSumRects.CIRCUMSCRIBED; break;
  110.             case 'I': case 'i': method = RiemannSumRects.INSCRIBED; break;
  111.             case 'T': case 't': method = RiemannSumRects.TRAPEZOID; break;
  112.          }
  113.       }
  114.      
  115.       if ("yes".equalsIgnoreCase( getParameter("UseMethodInput", "yes") )) {
  116.          methodChoice = new Choice();
  117.          methodChoice.add("Left Endpoint");
  118.          methodChoice.add("Right Endpoint");
  119.          methodChoice.add("Midpoint");
  120.          methodChoice.add("~Circumscribed");
  121.          methodChoice.add("~Inscribed");
  122.          methodChoice.add("Trapezoid");
  123.          methodChoice.select(method);
  124.          methodChoice.addItemListener(this);
  125.       }
  126.      
  127.       sums = new RiemannSumRects(func,intervals);
  128.       sums.setMethod(method);
  129.       canvas.add(sums);
  130.      
  131.       Color c = getColorParam("RectColor");
  132.       if (c != null)
  133.          sums.setColor(c);
  134.       c = getColorParam("OutlineColor");
  135.       if (c != null)
  136.          sums.setOutlineColor(c);
  137.          
  138.       super.setUpCanvas();  // Do the common setup: Add the axes, for example.
  139.       canvas.getCoordinateRect().setGap(10);  // Extra space around edges.
  140.       canvas.add(graph);  // Add the graph to the canvas.
  141.      
  142.       // Add a DrawString to the canvas to show the value of the sum.
  143.  
  144.       DrawString ds = new DrawString("sum = #", DrawString.TOP_LEFT,
  145.                            new Value[] { sums.getValueObject(RiemannSumRects.CURRENT_METHOD) } );
  146.       ds.setBackgroundColor(getColorParam("TextBackground",Color.white));
  147.       ds.setColor(getColorParam("TextColor",Color.black));
  148.       ds.setFrameWidth(1);
  149.       canvas.add(ds);
  150.      
  151.       mainController.add(ds);
  152.       mainController.add(sums);
  153.       if (intCtInput != null)
  154.          intCtInput.setOnUserAction(mainController);
  155.       canvas.getCoordinateRect().setOnChange(mainController);
  156.  
  157.    } // end setUpCanvas()
  158.    
  159.    
  160.  
  161.    protected void setUpMainPanel() {
  162.          // Override this method to add the methodChoice menu and interval count inputs, if any,
  163.          // to the panel.  (They were created in the setUpCanvas method.)
  164.    
  165.       super.setUpMainPanel(); // Do the common setup
  166.      
  167.       if (methodChoice == null && intCtInput == null)
  168.          return;
  169.          
  170.          JCMPanel panel = new JCMPanel();
  171.          panel.setLayout(new FlowLayout());
  172.          panel.setBackground(getColorParam("PanelBackground",Color.lightGray));
  173.          if (intCtInput != null) {
  174.             panel.add(new Label("Intervals:"));
  175.             panel.add(intCtInput);
  176.          }
  177.          if (methodChoice != null) {
  178.             panel.add(new Label("Method:"));
  179.             panel.add(methodChoice);
  180.          }      
  181.          if (inputPanel == null)
  182.             mainPanel.add(panel, BorderLayout.SOUTH);
  183.          else {
  184.             inputPanel.setBackground(getColorParam("PanelBackground",Color.lightGray));
  185.             inputPanel.add(panel, BorderLayout.SOUTH);
  186.          }
  187.      
  188.    } // end setUpMainPanel()
  189.    
  190.  
  191.  
  192.    protected void doLoadExample(String example) {
  193.          // This method is called when the user loads an example from the
  194.          // example menu (if there is one).  It overrides an empty method
  195.          // in GenericGraphApplet.
  196.          //   For this applet, the example string should contain
  197.          // an expression that defines the function to be graphed.
  198.          // This can optionally  be followed by a semicoloon and a list of four or five
  199.          // numbers.  The first four numbers give the x- and y- limes to be used for the
  200.          // example.  The fifth number, if present, gives the interval count.
  201.          // After the numbers, there can be another semicolon
  202.          // and the name of the summation method to be used.
  203.  
  204.       int pos = example.indexOf(";");
  205.  
  206.       double[] limits = { -5,5,-5,5 };  // x- and y-limits to use
  207.      
  208.       if (pos > 0) { // get limits, method from example text
  209.          String limitsText = example.substring(pos+1);
  210.          example = example.substring(0,pos);
  211.          pos = limitsText.indexOf(";");
  212.          if (pos > 0) {  // data includes a method name.
  213.             String methodStr = limitsText.substring(pos+1).trim();
  214.             limitsText = limitsText.substring(0,pos);
  215.             if (methodStr.length() > 0) {
  216.                 int method;
  217.                 switch (methodStr.charAt(0)) {
  218.                    case 'L': case 'l': method = RiemannSumRects.LEFTENDPOINT; break;
  219.                    case 'R': case 'r': method = RiemannSumRects.RIGHTENDPOINT; break;
  220.                    case 'M': case 'm': method = RiemannSumRects.MIDPOINT; break;
  221.                    case 'C': case 'c': method = RiemannSumRects.CIRCUMSCRIBED; break;
  222.                    case 'I': case 'i': method = RiemannSumRects.INSCRIBED; break;
  223.                    case 'T': case 't': method = RiemannSumRects.TRAPEZOID; break;
  224.                    default: method = -1;
  225.                }
  226.                if (method >= 0) {
  227.                   sums.setMethod(method);
  228.                   if (methodChoice != null)  
  229.                      methodChoice.select(method);
  230.                }
  231.             }
  232.          }
  233.          StringTokenizer toks = new StringTokenizer(limitsText, " ,");
  234.          if (toks.countTokens() >= 4) {
  235.             for (int i = 0; i < 4; i++) {
  236.                try {
  237.                    Double d = new Double(toks.nextToken());
  238.                    limits[i] = d.doubleValue();
  239.                }
  240.                catch (NumberFormatException e) {
  241.                }
  242.             }
  243.             if (toks.countTokens() > 0) {
  244.                   // get number of intervals
  245.                try {
  246.                    Double d = new Double(toks.nextToken());
  247.                    double intCtD = d.doubleValue();
  248.                    if (intCtD < 1)
  249.                       intCtD = 1;
  250.                    else if (intCtD > 5000)
  251.                       intCtD = 5000;
  252.                    intervals.setVal((int)(intCtD + 0.5));
  253.                }
  254.                catch (NumberFormatException e) {
  255.                }
  256.             }
  257.          }
  258.       }
  259.      
  260.       // Set up the example data and recompute everything.
  261.  
  262.       if (functionInput != null) {
  263.             // If there is a function input box, put the example text in it.
  264.          functionInput.setText(example);
  265.       }
  266.       else {
  267.            // If there is no user input, set the function in the graph directly.
  268.            // Also, in this case, func is a "WrapperFunction".  Set the
  269.            // definition of that WrapperFunction to be the same as f
  270.          try {
  271.             Function f = new SimpleFunction( parser.parse(example), xVar );
  272.             ((WrapperFunction)func).setFunction(f);
  273.          }
  274.          catch (ParseError e) {  
  275.              // There should't be parse error's in the Web-page
  276.              // author's examples!  If there are, the function
  277.              // just won't change.
  278.          }
  279.       }
  280.       CoordinateRect coords = canvas.getCoordinateRect(0);
  281.       coords.setLimits(limits);
  282.       coords.setRestoreBuffer();
  283.       mainController.compute();
  284.      
  285.    } // end doLoadExample()
  286.    
  287.  
  288.  
  289. } // end class RiemannSums
  290.