Animated Graph : Curve « Advanced Graphics « Java






Animated Graph

Animated Graph
/*************************************************************************
*                                                                        *
*  This source code file, and compiled classes derived from it, can      *
*  be used and distributed without restriction, including for commercial *
*  use.  (Attribution is not required but is appreciated.)               * 
*                                                                        *
*   David J. Eck                                                         *
*   Department of Mathematics and Computer Science                       *
*   Hobart and William Smith Colleges                                    *
*   Geneva, New York 14456,   USA                                        *
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
*                                                                        *
*************************************************************************/

// An applet belonging to the class AnimatedGraph displays a graph
// of a function that can depend on a parameter.  The value of the 
// parameter can be "animated" so that it ranges from one value ot
// another over a sequence of frames.

import java.awt.*;
import java.applet.Applet;
import java.util.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;


public class AnimatedGraph extends GenericGraphApplet {


   // Declare some private variables that are created in one method in
   // this class and used in a second method.

   private Function func;   // The function that is graphed.
   private Graph1D graph;   // The graph of the function.
   
   private Animator animator; // Animates the graph
   private Variable kVar;   // The parameter variable
   
   private VariableInput kMin, kMax, kIntervals;  // min, max, and number of intervals for the animator.  Might be null.


   protected void setUpParser() {  // Override this to create the animator and add its variable to the parser.
   
      int options = Animator.START_STOP_BUTTON | Animator.PAUSE_BUTTON  | Animator.LOOP_CHOICE;
      if  ( ! "no".equalsIgnoreCase(getParameter("UseNextAndPrev","yes")) )
         options |=  Animator.PREV_BUTTON | Animator.NEXT_BUTTON;
      animator = new Animator(options);
      kVar = animator.getValueAsVariable( getParameter("Parameter","k") );   
      parser.add(kVar);
      
      super.setUpParser();

      parameterDefaults = new Hashtable();
      String defaultFunction = xVar.getName() + " / (" + kVar.getName() + " - " + xVar.getName() + "^2)";
      parameterDefaults.put("Function",defaultFunction);
      if (! "no".equalsIgnoreCase(getParameter("UseAnimatorInputs")))
         parameterDefaults.put("TwoLimitsColumns","yes"); // change default if we need space for animator inputs
      
   } // end setUpParser()
   

   protected void setUpBottomPanel() {  // Overridden to add the sliders at the bottom of the applet.

      super.setUpBottomPanel();  // Do the default setup.
      
      // If there is a functionInput box, then the SOUTH position of the mainPanel already contains
      // the inputPanel that contains that box.  If so, add the animator to the SOUTH position of
      // the inputPanel.  (This is a good place, in general, to put extra input objects.)
      // If there is no inputPanel, then the SOUTH position of the mainPanel is empty, so put
      // the animator there.
      
      if (inputPanel != null)
         inputPanel.add(animator, BorderLayout.SOUTH);
      else
         mainPanel.add(animator, BorderLayout.SOUTH);

   } // end setUpBottomPanel()



   protected void setUpCanvas() { // Overridden to add the graph to the canvas and do other chores.

      super.setUpCanvas();  // Do the default setup.

      // When setUpCanvas() is called, the functionInput already exists, if one is
      // to be used, since it is created in setUpBopttomPanel(), which is called
      // before setUpCanvas.  If functionInput exists, add a graph of the function
      // from functionInput to the canvas.  If not, create a graph of the function
      // specified by the parameter named "Function" (or use sin(k*x) if none is specified).

      if (functionInput != null)
         func = functionInput.getFunction(xVar);
      else {
         String def = getParameter("Function");  // default value is set in setUpParser()
         func = new SimpleFunction( parser.parse(def), xVar );
      }

      // Create a graph of the function and add it to the canvas.
      
      graph = new Graph1D(func);
      graph.setColor(getColorParam("GraphColor", Color.magenta));
      canvas.add(graph);
      
      // Set up the min, max, and intervals property of the animator
      
      if  (! "no".equalsIgnoreCase(getParameter("UseAnimatorInputs"))) {
         kMin = new VariableInput(kVar.getName() + "Start",getParameter("ParameterMin","-2"));
         kMax = new VariableInput(kVar.getName() + "End",getParameter("ParameterMax","2"));
         kIntervals = new VariableInput("Intervals", getParameter("Intervals","25"));
         kIntervals.setInputStyle(VariableInput.INTEGER);
         kIntervals.setMin(1);
         kIntervals.setMax(1000);
         kMin.setOnUserAction(mainController);
         kMax.setOnUserAction(mainController);
         kIntervals.setOnUserAction(mainController);
         animator.setMin(kMin);
         animator.setMax(kMax);
         animator.setIntervals(kIntervals);
         if (limitsPanel != null) {
               // componets will be added to limitsPanel in setUpLimitsPanel()
            mainController.add(kMin);  // This is not done automatically, since they are in a limits panel  
            mainController.add(kMax);
            mainController.add(kIntervals);
         }
         else {
            JCMPanel ap = new JCMPanel(9,0);
            ap.setBackground(getColorParam("PanelBackground", Color.lightGray));
            ap.add(new Label(kMin.getName()));
            ap.add(kMin);
            ap.add(new Label());
            ap.add(new Label(kMax.getName()));
            ap.add(kMax);
            ap.add(new Label());
            ap.add(new Label(kIntervals.getName()));
            ap.add(kIntervals);
            ap.add(new Label());
            mainPanel.add(ap,BorderLayout.EAST);
         }
      }
      else {
         try {
            animator.setMin( (new Double(getParameter("ParameterMin","-2"))).doubleValue() );
            animator.setMax( (new Double(getParameter("ParameterMax","2"))).doubleValue() );
            animator.setIntervals( (int)Math.round((new Double(getParameter("Intervals","25"))).doubleValue()) );
         }
         catch (NumberFormatException e) {
         }
      }
      animator.setOnChange(mainController);

      // Add a DrawString to show the current value of the parameter

      if ( ! "no".equalsIgnoreCase(getParameter("ShowParameter","yes")) ) {
         DrawString param = new DrawString(kVar.getName() + " = #", DrawString.BOTTOM_LEFT, new Value[] { kVar });
         param.setBackgroundColor(canvas.getBackground());
         Color c = getColorParam("ParameterColor",Color.black);
         param.setColor(c);
         canvas.add(param);
      }

   } // end setUpCanvas


   protected void setUpLimitsPanel() {
     super.setUpLimitsPanel();
     if (limitsPanel != null && kMin != null) {  // add animator inputs to limits panel
         limitsPanel.addComponentPair(kMin,kMax);
         limitsPanel.addComponent(kIntervals);
     }
   }
 

   protected void doLoadExample(String example) {
         // This method is called when the user loads an example from the 
         // example menu (if there is one).  It overrides an empty method
         // in GenericGraphApplet.
         //   For the AnimatedGraph applet, the example string should contain
         // an expression that defines the function to be graphed.  This can optionally
         // be followed by a semicolon and a list of four to nine numbers.
         // The first four numbers give the x- and y-limits to be used for the
         // example.  If they are not present, then -5,5,-5,5 is used.  The
         // next three numbers specify the minimum value for the parameter, the
         // maximum number, and the number of intervals in the animation.
         // The eigth number, if present, specifies the starting loop style
         // for the animation with the following code:  0 for once-through,
         // 1 for loop, and 2 for back-and-forth.  The ninth number, if
         // present, tells whether to start the animation immediately upon
         // loading.  If it is 1, the animation is started.  If it is
         // not specified or is any value other than 1, the animation is not started.
         
      animator.stop();
         
      int pos = example.indexOf(";");
      boolean startAnimation = false;
      double[] limits = { -5,5,-5,5 }; // x- and y-limits to use

      if (pos > 0) { 
               // Get limits from example text.
         String nums = example.substring(pos+1);
         example = example.substring(0,pos);
         StringTokenizer toks = new StringTokenizer(nums, " ,");
         if (toks.countTokens() >= 4) {
            for (int i = 0; i < 4; i++) {
               try {
                   Double d = new Double(toks.nextToken());
                   limits[i] = d.doubleValue();
               }
               catch (NumberFormatException e) {
               }
            }
         }
         if (toks.hasMoreTokens()) {
            try {
               double d = (new Double(toks.nextToken())).doubleValue();
               if (kMin == null)
                  animator.setMin(d);
               else
                  kMin.setVal(d);
            }
            catch (NumberFormatException e) {
            }
         }
         if (toks.hasMoreTokens()) {
            try {
               double d = (new Double(toks.nextToken())).doubleValue();
               if (kMax == null)
                  animator.setMax(d);
               else
                  kMax.setVal(d);
            }
            catch (NumberFormatException e) {
            }
         }
         if (toks.hasMoreTokens()) {
            try {
               int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
               if (kIntervals == null)
                  animator.setIntervals(d);
               else
                  kIntervals.setVal(d);
            }
            catch (NumberFormatException e) {
            }
         }
         if (toks.hasMoreTokens()) {
            try {
               int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
               animator.setLoopStyle(d);
            }
            catch (NumberFormatException e) {
            }
         }
         if (toks.hasMoreTokens()) {
            try {
               int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
               startAnimation = (d == 1);
            }
            catch (NumberFormatException e) {
            }
         }
      }
      
      // Set up the example data and recompute everything.

      if (functionInput != null) {
            // If there is a function input box, put the example text in it.
         functionInput.setText(example);
      }
      else { 
           // If there is no user input, set the function in the graph directly.
         try {
            func = new SimpleFunction( parser.parse(example), xVar );
            graph.setFunction(func);
         }
         catch (ParseError e) {  
             // There should't be parse error's in the Web-page
             // author's examples!  If there are, the function
             // just won't change.
         }
      }
      CoordinateRect coords = canvas.getCoordinateRect(0);
      coords.setLimits(limits);
      coords.setRestoreBuffer();
      mainController.compute();
      if (startAnimation) {
         try {  // insert a small delay before animation starts
            synchronized(this) {
               wait(250);
            }
         }
         catch (InterruptedException e) {
         }
         animator.start();
      }
      
   } // end doLoadExample()
   
   public void stop() {  // stop animator when applet is stopped
      animator.stop();
      super.stop();
   }
 
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new AnimatedGraph();
         app.init();
         
         f.getContentPane().add (app);

         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }   
   
} // end class FamiliesOfGraphs


           
       








jcm1-source.zip( 532 k)

Related examples in the same category

1.Spline EditorSpline Editor
2.Draw SplineDraw Spline
3.Epsilon DeltaEpsilon Delta
4.Families Of GraphsFamilies Of Graphs
5.Integral CurvesIntegral Curves
6.Trace curveTrace curve
7.Input the function and draw the curveInput the function and draw the curve
8.Scatter PlotScatter Plot
9.Zoom interaction, Text background color, and the effect of transparencyZoom interaction, Text background color, and the effect of transparency