Archive

Posts Tagged ‘function’

Graphing Non-Functions

March 22, 2012 Comments off

My current gig is winding down, so this will probably be the last update on the function graphing engine for a while.  Although the function graphing engine is architected to graph cartesian or parameteric functions, only cartesian functions were supported in the initial release.  All functions defined in XML must implement an IPlottable interface, which means that evaluation and derivative methods are interpreted with y as a strict function of x.  All functions must be marked as cartesian, since a parametric function will not plot in the initial implementation.

What about non-functions, that is cases where y is not strictly a function of x?  As the saying goes, there is always a back door.  Functions may identify themselves as self-plotting.  In this case, the engine does not sample the function.  Instead, it provides the function with all the relevant information regarding the current graph window and calls the function’s plot() method.  A self-plotting function is welcome to draw anything it pleases, including Bezier curves, conic sections, spirals, or even smiley faces 🙂

Problems may arise with derived functions, however, i.e. other functions that derive their visual display from the definition of another function.  A graphical Marker function is a perfect example.  The Marker is an artist-generated, interactive graphic asset that is constrained to the path of another function.  If domain values exist for which there is not a unique range value, then Marker movement is unpredictable.

This example shows how to work around the non-function issue to a degree.  It plots parabolas that open upward, downward, and to the left or right.  More specifically, the parabola directrix is either parallel to the x or y axis.  Parallel to the x-axis is good.  Parallel to the y-axis causes problems.

Suppose we want a Marker constrained to the parabola along with a display of the tangent and normal, as well as the directrix.  The fixed distance from the point on the parabola to the directrix and axis of symmetry is also drawn.

Of the four use cases, the Marker follows y as a function of x in two and x as a function of y in the other two.  We can’t use the function graphing engine to manage the Marker display as it always calls the base function (parabola) eval() method with an input x-coordinate.  The derivative and normal displays won’t work in two cases because dy/dx is not uniquely defined.

In general, the equation of a parabola with vertex (h,k), focus (h,k+p), and directrix y=k-p is given by

(x-h)2 = 4p(y-k)

which allows y to be defined as a function of x, or x as a function of y.  There are really only two use cases requiring consideration, directrix parallel to the y-axis and directrix parallel to the x-axis.  In one case, horizontal mouse movement is used to position the Marker.  Vertical mouse movements control the Marker in the other case.

The custom Marker is composed directly into the custom Parabola function, which is marked as self-plotting.  This function is responsible for creating the Marker and controlling its placement as well as drawing all supporting graphics.

The Parabola function is defined in XML as

<function id=”Parabola” class=”graph.tests.Parabola” params=”h:0,k:0,p:-1,parallelTo:y”>
<lineMetrics thickness=”2″ color=”0xff0000″ />
<data markerParams=”marker:graph.symbols.CustomMarkerSymbol,rolloverColor:0x9ACD32,digits:2″
markerCoord=”1″ >
<directrix thickness=”3″ color=”0x9933CC” alpha=”1″ lineStyle=”line_dashed” dashWidth=”6″ dashSpacing=”4″ />
<lineSet1 thickness=”2″ color=”0x0000ff” />
<lineSet2 thickness=”1″ color=”0x00ff00″ alpha=”0.5″/>
</data>
</function>

and the display is shown below.

The aspect ratio of this graph is not ideal for the example, but it’s adequate for illustrating the example.  Note that the custom Parabola function is welcome to plot not only the parabola, but as many supporting graphics as it likes.  The custom Marker may be dragged along the boundaries of the parabola and rollover displays the current y-coordinate by default.

A simple parameter change,  h:0,k:0,p:1,parallelTo:y, causes the parabola to open to the right.

Parametric function graphing should be supported in the future, providing for a more clean and general-purpose means to plot any general parabola and supporting visuals.  I thought this was an interesting example of how a decent architecture and simple concepts like Composition open up possibilities that do not seem possible based on the defined constraints of an engine.

Next post will be an update on new capability in the Freehand Drawing Library.

Advertisements

Graphing Freeform Functions And Derivative

March 14, 2012 Comments off

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 🙂

Recent Work XML Function Graphing Engine

March 7, 2011 1 comment

I’m in the process of creating permalinks to some significant recent projects, so I would be remiss not to include what I consider to be the most extensive project I’ve worked on in the last couple years (not to mention the most fun).  The AS3 function graphing class library allowed layout and many graphing details to be described in XML.  Perhaps the most unique feature of the library was the high level of interactivity.  The library supports multiple zoom levels (bounds of each zoom level specified in XML) and unlimited panning via dragging the graph display.  The code automatically redraws axes, labels, function graphs, and overlays while dragging.

A simple. blank graph (with default control panel) is shown below.

created with the following XML

<learningObject id="graph" x="0" y="0" width="100" height="100" display="{ALL}" graphType="" pannable="true" lockZoom="true" sampling="auto" hideControlsOnShapshot="true" >
<controls id="myControls" x="0" y="0" />
<learningObject id="background" />
<learningObject id="grid" />
<arrows color="0x000000" length="10" width="8" alpha="1" curvature="5" />
<learningObject id="title" />
</learningObject>

A robust library of predefined functions (AS3 classes written to a specific interface) exist to rapidly plot common functions over arbitrary open/closed intervals as shown in the following screenshot.

which is created from the following XML

<function id="complexStepfunc">
<lineMetrics thickness="2" color="0xff0000" />
<data d1="closed" d2="open" radius="4" openFill="0xffffff">
<interval left="-inf" right="-1" functionClass="graphing.functions.library.Polynomial" functionParams="-3,1,2" />
<interval left="0" right="10" functionClass="graphing.functions.library.SineWave" functionParams="a:2,b:1,c:1" />
</data>
</function>

More complex displays are created by deriving a function from another function. One simple example is the derivative of a function. All functions in the base library evaluate their first and second derivatives (or indicate that no such definition is available in which case derivatives are numerically approximated). The following example shows the plot of a cosine wave and its first derivative.

created with the following XML

<function id="cosine" >
<lineMetrics thickness="2" color="0x0000ff"/>
</function>
<function id="deriv"
derivedFrom="cosine">
<lineMetrics thickness="2" color="0xff0000"/>
</function>

The concept of derived functions allows a wide variety of plots from a single base function. The following example shows the plot of a tangent line that can be derived from any base function.

and its associated XML

<function id="tangentLine"
derivedFrom="cubic" params="length:auto" derivedParams="x-coord:1" plotType="LINEAR">
<lineMetrics thickness="2" color="0xff0000" />
</function>

I must admit that my favorite function display is freeform. Many functions are not re-used enough to support creating a function display class to fit into the graphing engine. Instead, these functions can be described in a calculator-like syntax with arbitrary parameters such as a, b, c, etc. Specific parameter values describe a unique plot of a family of functions as shown below.

and the XML

<function id="freeForm1" params="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>

A variety of ‘overlays’ are supported in the engine. The simplest is an interactive Marker or draggable visual symbol that follows the trace of a function. An example is shown below.

created from the following XML

<function id="cubic"
params="3,1,-1,0.5" plotType="LINEAR">
<lineMetrics thickness="2" color="0x0000ff" />
</function>
<function id="myMarker"
derivedFrom="cubic" params="marker:test.symbols.TangentMarkerSymbol,rolloverColor:0x9ACD32,digits:2" derivedParams="x-coord:1" >
</function>

On rollover, a tooltip-style displays shows the numerical value of the function and its first derivative.  Custom Markers are created by extending the Marker class.  The base library includes TangentMarker and SecantMarker classes that display a Marker along with tangent and secant lines.

Probes represent interactive overlays that are bound to the graph dimensions, not any specific function. On drag, they continuously dispatch a (bubbling) custom event, allowing information to be computed and displayed that depends on the current horizontal or vertical probe location. A horizontal Probe is shown below.

<probes>
<learningObject id="horProbe" y="-1" snap="0" color="0x000000" thickness="2" updateOnSnap="true"
symbol="test.symbols.Probe1Handle" showAllHandles="true" tipID="probe1" >
</learningObject>
</probes>

The MarkerProbe is an interesting overlay that has attributes of both a Marker and Probe. Its display is derived from a specific function, as shown in the following diagram and XML.

<probes>
<learningObject id="markerprobe"
x="0.5" snap="0" color="0x000000" thickness="2" updateOnSnap="true"
symbol="test.symbols.Probe1Handle" showAllHandles="true" derivedFrom="cubic" tipID="probe1" >
<params horVisible="true" vertVisible="true" />
<marker symbol="test.symbols.TangentMarkerSymbol" rolloverColor="0x9ACD32" digits="2"/>
<horizontalLine>
<text offset="2" >left</text>
<lineMetrics thickness="2" color="0x9933CC" alpha="1" lineStyle="line_solid" />
</horizontalLine>
<verticalLine>
<text offset="2">below</text>
<lineMetrics thickness="2" color="0x9933CC" alpha="1" lineStyle="line_dashed" dashWidth="6" dashSpacing="4" />
</verticalLine>
</learningObject>
</probes>

ShadedRegions are rectangular regions (some of which may extend infinitely) designed to draw attention to specific regions of the graph. Infinite regions are drawn as such when the graph pans as shown below.

<shadedRegions>
<learningObject id="region1"
fill="0xffcccc" alpha="0.5" points="0,1 0,3 4,3 4,0 3,0 3,1" >
<lineMetrics thickness="1" color="0x0000ff" alpha="1" />
</learningObject>
<learningObject id="region2"
fill="none" points="0,0 0,-3 +inf,-3 +inf,0">
<lineMetrics thickness="3" color="0xff0000" alpha="1" />
</learningObject>
</shadedRegions>

Highlights can be considered a non-rectangular type of ShadedRegion that are bound above or below by a function. These are used to emphasize the geometry of the area above or below a function.  Since these overlays are bound by a function, they must be derived from a function in XML.

<function id="quad"
params="-3,1,2" plotType="LINEAR">
<lineMetrics thickness="2" color="0x0000ff" alpha="1" />
</function>
<function id="quadHighlight" derivedFrom="quad" params="direction:above,color:0xff0000,alpha:0.2" />