The source file include class files, so this is a Flash MX 2004 movie. Otherwise, it can be done by Flash MX.
Evaluate the equation object
I have discussed in previous session how to parse a string and get the value of an equation. At the end, I also discussed how to handle an equation string with variables. So, it is not difficult to get the value of "sin(x)" when we set x=0.3;
When we draw equation graph, we need to sample many x values and get the result of the equation before we plot those data out. We can accomplish this by repeated setting x and parsing the equation to get a new result.
However, to parse an equation string, we need to screen each character for existance of parenthesis and existance of any operator in the operatorSet array. It is time consuming.
Since what gets changed is the variable value only, the existence and position of the operators and parenthesis are the same as before , repeated parsing is not necessary. We can store down the operators and parenthesis. That is what my EquationObject class serves.
By this algorithm, to handle 100 sample x and get 100 y value is not a hard job any more. My evaluator does not evaluate the equation string. It evaluate the instance of EquationObject.
In this movie, about 400 x values are sampled. This is faster and more efficient.
The fit of Y range
Here is the scenario. We set x and y range from 0 to 8. We plot the equation "sin(x)". Well, half of the y points fall into the negative region. That means half of the curve is out of the lower bound of the canvas. Besides, the curve is located low and occupies only one-eighth of the canvas leaving a large blank area in the upper half. This is ugly and stupid.
To correct this, we need to calculate the Y range of the curve. We walk through each y value in the y Array and pick the maximal value and minimal value. Calculate the y range by yMax-yMin so that we can plot and fit our curve to the canvas.The highest point of the curve should fall on the top edge of the canvas and the lowest point of the curve should fall on the bottom edge of the canvas.
Unfortunately, the policy is not always possible. There are bugs. Lets try to remove the bug.
P.S. in my source file, if we set yMin, yMax then the automatic fit function is disabled. This is necessary in some condition, such as doing a comparison between two equations.
The infinity - range too big
Check this scenario. How to plot the equation "1/x" with x ranging from -1 to 1 ?
When x=0, the value is infinity. Even worse, when x is near the x, the value 1/x is very very large. If we accept that y value, then the y range is very large. The curve is very ugly.
Can you guess what it had looked like ? Well, the graph shows a max point at the upper edge and all other points fall at the lower edge of the canvas. Yes, since the y range is very large, all values are zoomed out as if those values are nearly 0 except the max point.
To correct this, I have to skip off those infinity values or values that are un-acceptably large compared with other values. The algorithm should not be too complex. Flash can easily hang out for complex algorithm.
I write a simple script. I calculate the slope of the curve. When the curve is curving upward or downward too sharply, I take that point as infinity and skip it off. Mathematically, this algorithm may not be so reasonable, but it does serve our goal.
So, if we plot the equation "1/x" from -1 to 1, we see the points near the x=0 zone are missing.¡@
The flat line - range too small
Scenario: How to plot the equation "sin(x)^2+cos(x)^2" with whatever x range ?
Well, for any x value, the result theoretically is always 1. So we expect to see a flat line on our canvas. No ?
My script would try to put the maximum value at the upper edge and minimum value at the lower edge of the canvas. If the "curve" is a flat horizontal line, how could it possibly do this ?
Can you guess how this equation had been plot ? Well, the result is a bizzare up and down spike.
Flash has limitation in calculation of float point. Besides, the sin and cos functions are just giving estimated values. In fact, when Flash calculate sin(x)^2+cos(x)^2, it gives a value "almost" 1 but not just 1. So, the result of the plot is still a curve with minute up and down not just a flat line. Since the difference between y max and y min is minute, the range is minute and the zoom-in effect is large. The end result is magnification of the up and down of the curve.
To correct this, we add some script to rule out such condition. When y range is too small, we add 5 as its maximum value and subtract 5 as its minimum value.
make the grid scales
Scenario: If I my bottom value is 10.1 and top value is 90, I want to draw grid lines at position where it represent 20- 40- 60- 80 - that counts 4 grid lines. If the top value is 55, I would draw grid lines at 20-30-40-50- total 4 lines. If the top value is 30, then I draw lines at 15 - 20 - 25 -30 total 4 lines.
Principle 1 : I want to keep the number of grid lines around 4 lines, 3 or 5 are acceptable.
Principle 2 : I want the grid line position "rounded" to 0 or 5 if possible. Positions such as 53- 76 -99 -122 should be avoid. In stead, I would hope it to be 50 - 75 -100 -125, although it may be one line more or less.
Well, it is more difficult than I had expected. So, I can not but use a brutal way.
First, I estimate what is the power of 10 for the space. Is it 0.01, or 0.1, or 1 or 10, or 100, or 1000 ? This is done through the log10. The script is like this : Math.floor(Math.log(dx)/Math.LN10);
For a result such as 10, then I test 2, 5, 10, 20, 50 and see how many lines I need to draw, if it counts less than 5, accept it.
If anyone knows a better way, please email me. I would appreciate sincerely.
Here is scenario: Plot a graph on to a canvas of 300-pixel-wide for equation "y=sin(x)", with x=-300 to 300.
The result is very ugly and useless because we plot it with in-adequate x sampling. Not every "peak" of the sin wave gets caught. So, not only the straight lines replace the curves, the repeated peaks in the graph do not sit at the same height as we expected.
Lets go back to that scenario. How about plot is with x range 0 to 8. The result is a beautiful curve. Is this beautiful sin wave plot accurate enough ? Here we see two peaks. Are they at the same height ? No. Not exactly.
The peak should occurr when x=(Math.PI)/2 , around half of 3.14159..... I dont think we pick that point exactly.
Theoretically, the peak when x=PI/2 should be at height of 1. No, in our graph, no single Y value is exactly 1.
How many sampling is "enough" ? I dont think there is an easy answer.¡@
The equation grapher
download source fla