Graphing Freeform Functions And Derivative

I’m currently working on an interactive set of unit tests for the function graphing engine I wrote over three years ago.  We’ve made some hasty modifications to the engine over the last six months and only tested the mods within the actual learning applications.  The engine is now sufficiently complex that I’m worried about making changes in one area that have undesired consequences in another area.

This unit test engine allows any number of specific graph tests to be coded to an IGraphTest interface and added in XML.  The ComboBoxes for selecting graph tests and functions inside those tests are auto-populated based on XML data.

One of my favorite features of the graph engine (and the least tested) is freeform function input.  In the past, freeform functions and parameter values were defined completely in XML, i.e.

<function id=”freeForm1″ class=”graphing.functions.library.FreeFormparams=”1,-1,2,1″>
<data vars=”a,b,c,d,x” function=”a*x + b*x^2 – 3*sin(c*x) + d*x^3″ />
<lineMetrics thickness=”2″ color=”0xff0000″ />
</function>

The data node defines parameters a, b, c, and d that may take on any real value. The independent variable is x.  The params attribute in the function node defines the actual parameter values.  Function parsing is handled by an independent class that may be used in any other application, independent of the graphing engine.

That’s all well and good, but I wanted to test the ability to define functions and parameters programmatically, specifically typing a function into an input text field.  In this test, the XML looks like

<learningObject id=”testGraph” class=”graphing.functions.FunctionPlot”
x=”25″ y=”60″ width=”350″ height=”280″ display=”freeForm” pannable=”true” >

.
.
.

<function id=”freeForm” class=”graphing.functions.library.FreeForm” >
<lineMetrics thickness=”2″ color=”0xff0000″ />
</function>
<function id=”deriv” class=”graphing.functions.library.Derivative”
derivedFrom=”freeForm”>
<lineMetrics thickness=”2″ color=”0x0000ff”/>
</function>

The graph engine displays an initially undefined function (I had to correct a couple of typos to get that to work). A function is defined in XML (the Derivative) that is derived from that undefined freeform function (yes, two more corrections there).

The function is typed into an input box in the test application.  Spinners are used to set parameter values.  The code automatically determines the presence of a, b, c, and d  parameters and disables spinners for which there are no parameters in the function.  That was a little tricky, because of situations where ‘c’ may be used as a parameter or in the function, i.e. sin(c*x) vs. cos(x).

Here is a screenshot of a simple example with the first derivative automatically computed from the freeform function definition.  Each function is coded to a specific interface and must be able to evaluate itself and its first derivative.  Although I’d like to get into symbolic differentiation one day, the current approach is numerical and it uses an adaptive differencing algorithm based on graph scale.

It is, without question, the ugliest demo you will ever see, but its sole purpose is to facilitate rapid unit testing of both new functionality and prior capability that is to be used in new ways.

I’m really liking the freeform graphing now that it can be done purely programmatically and I’ve almost decided to add symbolic differentiation to my bucket list 🙂

Advertisement