Subversion Repositories wimsdev

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3653 schaersvoo 1
/* jm.evers 10/2009
2
 
3
 This is just a copy of Parametric.java ;  added a param "showAll"
4
 <param name="showAll" value="0/no"> will show the graph and no input controls
5
 Any other values will revert to Parametric.java behaviour.
6
 
7
 The evalues used to generate the parametric figure are however
8
 still easy to be read by pupils looking at the page source...
9
 
10
example:
11
<html>
12
    <body>
13
        <applet archive="./jcm.jar" code="SilentParametric.class" width="640" height="360">
14
            <param name="showAll" value="no"><!-- yes will give user inputs -->
15
            <param name="FrameTitle" value="Parametric Curves">
16
            <param name="UseGrid" value="yes">
17
            <param name="Limits" value="-1.5,1.5,-1.5,1.5">
18
            <param name="UseMouseZoom" value="no">
19
            <param name="UsePanner" value="no">
20
            <param name="UseFunctionInput" value="no">
21
            <param name="UseParamInputs" value="no">
22
            <param name="UseRestoreButton" value="yes">
23
            <param name="UseEqualizeButton" value="yes">
24
            <param name="SetLimitsButton" value="yes">
25
            <param name="UseZoomButtons" value="yes">
26
 
27
            <param name="LoopStyle" value="2"><!-- 0,1,2 0=once,1=restart,2=back and forth-->
28
            <param name="File" value="http://localhost/test.data">
29
<!--
30
or define functions through params:
31
            <param name="Function" value="sin(1/2*t)">
32
            <param name="Function2" value="sin(2*t)">
33
-->
34
            <param name="FunctionLabel" value="x(t)">
35
            <param name="FunctionLabel2" value="y(t)">
36
            <param name="TracerIntervals" value="150">
37
            <param name="ParameterMin" value="0">
38
            <param name="ParameterMax" value="2*pi/(1/2)">
39
            <param name="PanelBackground" value="255 235 245">
40
            <param name="UseComputeButton" value="no">
41
            <param name="TwoLimitsColumns" value="no">
42
            <param name="UseLimitsPanel" value="no">
43
            <param namr="Insets" value="no">
44
            <param name="BackgroundColor" value="255 235 245">
45
        </applet>
46
    </body>
47
</html>
48
*/
49
 
50
/*************************************************************************
51
*                                                                        *
52
*  This source code file, and compiled classes derived from it, can      *
53
*  be used and distributed without restriction, including for commercial *
54
*  use.  (Attribution is not required but is appreciated.)               *
55
*                                                                        *
56
*   David J. Eck                                                         *
57
*   Department of Mathematics and Computer Science                       *
58
*   Hobart and William Smith Colleges                                    *
59
*   Geneva, New York 14456,   USA                                        *
60
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
61
*                                                                        *
62
*************************************************************************/
63
 
64
 
65
// The ParametricCurve applet is a configurable applet that displays a parametric
66
// curve defined by two functions of a parameter t.  There can be a "Tracer" button
67
// on the applet.  When the user clicks this button, a crosshair is moved along
68
// the curve from beginning to end.
69
 
70
import java.awt.*;
71
import java.applet.Applet;
72
import java.util.StringTokenizer;
73
import java.util.Hashtable;
74
import edu.hws.jcm.draw.*;
75
import edu.hws.jcm.data.*;
76
import edu.hws.jcm.functions.*;
77
import edu.hws.jcm.awt.*;
78
import java.net.*;
79
import java.io.*;
80
 
81
 
82
public class SilentParametric extends GenericGraphApplet {
83
 
84
   // Declare some private variables that are created in one method in
85
   // this class and used in a second method.
86
 
87
   private Function xFunc,yFunc;    // The functions that are graphed.
88
   private ParametricCurve graph;   // The graph of the function.
89
   private Animator tracer;         // for tracing the curve by moving a crosshair along it
90
   private Crosshair crosshair;     // Crosshair used for tracing the graph
91
   private VariableInput tMin,tMax; // for inputting limits on t
92
   private VariableInput tIntervals; // for inutting the number of intervals into which the t-range is divided
93
   private ExpressionInput functionInput2;  // for inputting yFunc; xFunc is input in functionInput
94
   public String tMaxString="2";
95
   public String tMinString="-2";
96
 
97
   protected void setUpParameterDefaults() {
98
      parameterDefaults = new Hashtable();
99
      parameterDefaults.put("TwoLimitsColumns", "yes");
100
      parameterDefaults.put("Variable","t");
101
      parameterDefaults.put("XName","x");  // we need this so that xmin and xmax boxes are labeled correctly;
102
                                           // without it, the name would come from the variable name, t, instead of x
103
      parameterDefaults.put("FunctionLabel", "  " + getParameter("XName") + "(" + getParameter("Variable") + ") = ");
104
      parameterDefaults.put("FunctionLabel2", "  " + getParameter("YName","y") + "(" + getParameter("Variable") + ") = ");
105
   }
106
 
107
   protected void setUpCanvas() {  // Override this to add more stuff to the canvas.
108
 
109
      super.setUpCanvas();  // Do the common setup: Add the axes and
110
 
111
      // When setUpCanvas is called, the function inputs already exist, if they are
112
      // to be used, since they are created in setUpBopttomPanel(), which is called
113
      // before setUpCanvas().  If functionInput exists, add a graph of the functions
114
      // from functionInput and functionInput2 to the canvas.  If not, create a graph 
115
      // of the functions specified by the parameters named "Function" and "Function2".
116
 
117
      if (functionInput != null) {
118
         xFunc = functionInput.getFunction(xVar);
119
         yFunc = functionInput2.getFunction(xVar);
120
      }
121
      else {
122
         String xFuncDef = " cos(" + xVar.getName() + ") + cos(3*" + xVar.getName() + ")";
123
         String yFuncDef = " sin(4*" + xVar.getName() + ") - sin(2*" + xVar.getName() + ")";
124
         String file = getParameter("File");
125
// jm.evers begin
126
         if(file != null){
127
            //System.out.println("fetching data from "+file);
128
            String newdata="";
129
            try{ newdata = load(file);
130
                // scheme: function1,function2,min,max
131
                StringTokenizer t = new StringTokenizer(newdata, ",");
132
                if(t.countTokens() != 4) {System.out.println("scheme is: function1,function2,min,max");}
133
                else {
134
                    xFuncDef = t.nextToken();
135
                    yFuncDef = t.nextToken();
136
                    tMinString = t.nextToken();
137
                    tMaxString = t.nextToken();
138
                }
139
            } catch(Exception e){System.out.println("Could not read data from "+file);}
140
         }
141
         else
142
         {
143
            xFuncDef = getParameter("Function", xFuncDef);
144
            yFuncDef = getParameter("Function2", yFuncDef);
145
         }
146
// jm.evers end
147
         Function f = new SimpleFunction( parser.parse(xFuncDef), xVar );
148
         xFunc = new WrapperFunction(f);
149
         f = new SimpleFunction( parser.parse(yFuncDef), xVar );
150
         yFunc = new WrapperFunction(f);
151
      }
152
      graph = new ParametricCurve(xFunc,yFunc);
153
      Color color = getColorParam("CurveColor");
154
      if (color != null)
155
         graph.setColor(color);
156
 
157
      // if inputs are desired to control the parameter on the curve, set them up here
158
 
159
      if  ("no".equalsIgnoreCase(getParameter("UseParamInputs","yes"))) {
160
         tMin = new VariableInput(xVar.getName() + "Start",tMinString);
161
         tMax = new VariableInput(xVar.getName() + "End",tMaxString);
162
         tIntervals = new VariableInput("Intervals", getParameter("Intervals","500"));
163
         tIntervals.setInputStyle(VariableInput.INTEGER);
164
         tIntervals.setMin(1);
165
         tIntervals.setMax(5000);
166
         tMin.setOnUserAction(mainController);
167
         tMax.setOnUserAction(mainController);
168
         tIntervals.setOnUserAction(mainController);
169
         graph.setTMin(tMin);
170
         graph.setTMax(tMax);
171
         graph.setIntervals(tIntervals);
172
        // jm.evers begin
173
        String s = getParameter("showAll");
174
        boolean showAll=true;
175
        if(s.equalsIgnoreCase("no") || s.equalsIgnoreCase("0")){showAll=false;}
176
        // jm.evers end  
177
         if(showAll){
178
            if (limitsPanel != null) {
179
               // componets will be added to limitsPanel in setUpLimitsPanel()
180
                mainController.add(tMin);  // This is not done automatically, since they are in a limits panel  
181
                mainController.add(tMax);
182
                mainController.add(tIntervals);
183
            }
184
             else {
185
                JCMPanel ap = new JCMPanel(9,0);
186
                ap.setBackground(getColorParam("PanelBackground", Color.lightGray));
187
                ap.add(new Label(tMin.getName()));
188
                ap.add(tMin);
189
                ap.add(new Label());
190
                ap.add(new Label(tMax.getName()));
191
                ap.add(tMax);
192
                ap.add(new Label());
193
                ap.add(new Label(tIntervals.getName()));
194
                ap.add(tIntervals);
195
                ap.add(new Label());
196
                mainPanel.add(ap,BorderLayout.EAST);
197
            }
198
        }
199
      }
200
      else {
201
         try {
202
            graph.setTMin( new Constant((new Double(tMinString)).doubleValue()) );
203
            graph.setTMax( new Constant((new Double(tMaxString)).doubleValue()) );
204
            graph.setIntervals( new Constant((new Double(getParameter("Intervals","500"))).doubleValue()) );
205
         }
206
         catch (NumberFormatException e) {
207
         }
208
      }
209
 
210
      // If the applet is configured to have a tracer button, create it and add the crosshair to the canvas
211
 
212
      if (! "no".equalsIgnoreCase( getParameter("UseTracer","yes") ) ) {
213
         tracer = new Animator();
214
         String loopstyle=getParameter("LoopStyle");
215
         if(loopstyle != null){
216
            if(loopstyle.equals("0")){tracer.setLoopStyle(0);}
217
            else
218
            if(loopstyle.equals("1")){tracer.setLoopStyle(1);}
219
            else
220
            if(loopstyle.equals("2")){tracer.setLoopStyle(2);}
221
            else
222
            tracer.setLoopStyle(2);
223
        }
224
         tracer.setMin(graph.getTMin());
225
         tracer.setMax(graph.getTMax());
226
         tracer.setUndefinedWhenNotRunning(true);
227
         tracer.setStartButtonName("Trace Curve!");
228
         double[] d = getNumericParam("TracerIntervals");
229
         int ints;
230
         if (d == null || d.length != 1)
231
            ints = 100;
232
         else
233
            ints = (int)Math.round(d[0]);
234
         if (ints <= 0)
235
            tracer.setIntervals(graph.getIntervals());
236
         else
237
            tracer.setIntervals(ints);
238
         Variable v = tracer.getValueAsVariable();
239
         crosshair = new Crosshair( new ValueMath(xFunc,v), new ValueMath(yFunc,v) );
240
         crosshair.setLineWidth(3);
241
         crosshair.setColor(getColorParam("CrosshairColor",Color.gray));
242
         canvas.add(crosshair);
243
 
244
         if (inputPanel != null) {
245
            inputPanel.add(tracer,BorderLayout.WEST);
246
         }
247
         else if (limitsPanel == null) {
248
            Panel p = new Panel();
249
            p.add(tracer);
250
            mainPanel.add(p,BorderLayout.SOUTH);
251
         }
252
         // if inputPanel is null but limitsPanel is not null, the tracer will be
253
         //    added to the limit control panel in setUpLimitsPanel()
254
      }
255
 
256
      canvas.add(graph);  // Finally, add the graph to the canvas.
257
 
258
   } // end setUpCanvas()
259
 
260
 
261
   protected void setUpLimitsPanel() {
262
        super.setUpLimitsPanel();
263
         if (limitsPanel != null && tMin != null) {  // add parameter inputs to limits panel
264
             limitsPanel.addComponentPair(tMin,tMax);
265
             limitsPanel.addComponent(tIntervals);
266
         }
267
         if (inputPanel == null && tracer != null && limitsPanel != null)  {
268
             limitsPanel.addComponent(tracer);
269
         }
270
   }
271
 
272
 
273
   protected void setUpBottomPanel() { // override this to make a panel containing inputs for two functions
274
      if ( ! "no".equalsIgnoreCase(getParameter("UseFunctionInput", "yes")) ) {
275
 
276
         inputPanel = new JCMPanel();
277
         inputPanel.setBackground( getColorParam("PanelBackground", Color.lightGray) );
278
         Panel in = new JCMPanel(2,1);
279
         inputPanel.add(in,BorderLayout.CENTER);
280
 
281
         if ( ! "no".equalsIgnoreCase(getParameter("UseComputeButton", "yes")) ) {
282
            String cname = getParameter("ComputeButtonName", "New Functions");
283
            computeButton = new Button(cname);
284
            inputPanel.add(computeButton, BorderLayout.EAST);
285
            computeButton.addActionListener(this);
286
         }
287
 
288
         String varName = getParameter("Variable");
289
         String def = getParameter("Function");
290
         if (def == null)
291
            def = "cos(" + varName + ") + cos(3*" + varName + ")";
292
         functionInput = new ExpressionInput(def,parser);
293
         String label = getParameter("FunctionLabel");
294
         if ("none".equalsIgnoreCase(label))
295
            in.add(functionInput);
296
         else {
297
            Panel p = new JCMPanel();
298
            p.add(functionInput,BorderLayout.CENTER);
299
            p.add( new Label(label), BorderLayout.WEST );
300
            in.add(p);
301
         }
302
 
303
         def = getParameter("Function2");
304
         if (def == null)
305
            def = "sin(4*" + varName + ") - sin(2*" + varName + ")";
306
         functionInput2 = new ExpressionInput(def,parser);
307
         label = getParameter("FunctionLabel2");
308
         if ("none".equalsIgnoreCase(label))
309
            in.add(functionInput2);
310
         else {
311
            Panel p = new JCMPanel();
312
            p.add(functionInput2,BorderLayout.CENTER);
313
            p.add( new Label(label), BorderLayout.WEST );
314
            in.add(p);
315
         }
316
 
317
         mainPanel.add(inputPanel, BorderLayout.SOUTH);
318
         functionInput.setOnUserAction(mainController);
319
         functionInput2.setOnUserAction(mainController);
320
      }
321
   }
322
 
323
 
324
   protected void setUpMainPanel() { // Override to set up controller for tracer, if there is one
325
 
326
      super.setUpMainPanel(); // Do the common setup
327
 
328
      if ( tracer == null ) {
329
         return;  // If the applet is not configured to use a trace button, there is nothing to do.
330
      }
331
 
332
      Controller traceController = new Controller();  // A controler that will only recompute the crosshair position
333
      traceController.add(tracer);
334
      traceController.add(crosshair);
335
      tracer.setOnChange(traceController);
336
 
337
   } // end setUpMainPanel()
338
 
339
   protected void doLoadExample(String example) {
340
         // This method is called when the user loads an example from the 
341
         // example menu (if there is one).  It overrides an empty method
342
         // in GenericGraphApplet.
343
         //   For the Parametric applet, the example string should contain
344
         // two expression that defines the curve to be graphed, separated 
345
         // by a semicolon.  This can optionally
346
         // be followed by another semicolon and a list of four to seven numbers.
347
         // The first four numbers give the x- and y-limits to be used for the
348
         // example.  If they are not present, then -5,5,-5,5 is used.  The
349
         // next three numbers specify the minimum value for the parameter, the
350
         // maximum value, and the number of intervals into which the range of
351
         // parameter values is divided.
352
 
353
      if (tracer != null)
354
         tracer.stop();
355
 
356
      int pos = example.indexOf(";");
357
      if (pos == -1)
358
         return; // illegal example -- must have two functions
359
      String example2 = example.substring(pos+1);
360
      example = example.substring(0,pos);
361
      pos = example2.indexOf(";");  
362
 
363
 
364
      double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
365
 
366
      if (pos > 0) {
367
               // Get limits from example2 text.
368
         String nums = example2.substring(pos+1);
369
         example2 = example2.substring(0,pos);
370
         StringTokenizer toks = new StringTokenizer(nums, " ,");
371
         if (toks.countTokens() >= 4) {
372
            for (int i = 0; i < 4; i++) {
373
               try {
374
                   Double d = new Double(toks.nextToken());
375
                   limits[i] = d.doubleValue();
376
               }
377
               catch (NumberFormatException e) {
378
               }
379
            }
380
         }
381
         if (toks.hasMoreTokens()) {
382
            try {
383
               double d = (new Double(toks.nextToken())).doubleValue();
384
               if (tMin == null) {
385
                  graph.setTMin(new Constant(d));
386
                  if (tracer != null)
387
                     tracer.setMin(d);
388
               }
389
               else
390
                  tMin.setVal(d);
391
            }
392
            catch (NumberFormatException e) {
393
            }
394
         }
395
         if (toks.hasMoreTokens()) {
396
            try {
397
               double d = (new Double(toks.nextToken())).doubleValue();
398
               if (tMax == null) {
399
                  graph.setTMax(new Constant(d));
400
                  if (tracer != null)
401
                     tracer.setMax(d);
402
               }
403
               else
404
                  tMax.setVal(d);
405
            }
406
            catch (NumberFormatException e) {
407
            }
408
         }
409
         if (toks.hasMoreTokens()) {
410
            try {
411
               int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
412
               if (tIntervals == null) {
413
                  if (tracer != null && tracer.getIntervals() == graph.getIntervals())
414
                     tracer.setIntervals(d);
415
                  graph.setIntervals(new Constant(d));
416
               }
417
               else
418
                  tIntervals.setVal(d);
419
            }
420
            catch (NumberFormatException e) {
421
            }
422
         }
423
      }
424
 
425
      // Set up the example data and recompute everything.
426
 
427
      if (functionInput != null) {
428
            // If there is a function input box, put the example text in it.
429
         functionInput.setText(example);
430
         functionInput2.setText(example2);
431
      }
432
      else {
433
           // If there is no user input, set the function in the graph directly.
434
         try {
435
            Function f = new SimpleFunction( parser.parse(example), xVar );
436
            ((WrapperFunction)xFunc).setFunction(f);
437
            Function g = new SimpleFunction( parser.parse(example2), xVar );
438
            ((WrapperFunction)yFunc).setFunction(g);
439
         }
440
         catch (ParseError e) {  
441
             // There should't be parse error's in the Web-page
442
             // author's examples!  If there are, the function
443
             // just won't change.
444
         }
445
      }
446
      CoordinateRect coords = canvas.getCoordinateRect(0);
447
      coords.setLimits(limits);
448
      coords.setRestoreBuffer();
449
      mainController.compute();
450
 
451
   } // end doLoadExample()
452
 
453
 
454
   public void stop() {  // stop animator when applet is stopped
455
      if (tracer != null)
456
         tracer.stop();
457
      super.stop();
458
   }
459
 
460
 
461
// jm.evers; handy functions, not invented here :(
462
  public static byte [] loadURL(URL url) throws IOException {
463
        int bufSize = 1024 * 2;
464
        byte [] buf = new byte[bufSize];
465
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
466
        BufferedInputStream   in   = new BufferedInputStream(url.openStream());
467
        int n;
468
        while ((n = in.read(buf)) > 0){
469
            bout.write(buf, 0, n);
470
        }
471
        try { in.close(); } catch (Exception ignored) { }
472
        return bout.toByteArray();
473
    }
474
 
475
    public static String loadFile(String fname) throws IOException {
476
        byte[] bytes = loadURL(new URL("file:" + fname));
477
        return new String(bytes);
478
    }
479
 
480
    public static String load(String fileOrURL) throws IOException {
481
        try {
482
            URL url = new URL(fileOrURL);
483
            return new String(loadURL(url));}
484
            catch (Exception e) { return loadFile(fileOrURL);}
485
    }
486
}
487
// end class Parametric