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" />
Impressive.