Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3653 | schaersvoo | 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 |