Parametrized Graphics in Mathematica

Martin Kraus

Abstract: Displaying graphics with computers offers more possibilities for interaction than almost any other display technology can provide. For example, the viewer/user may change the viewpoint within a three-dimensional scene, choose a point in time in animated graphics, specify input points for a geometrical construction, or manipulate parameters of a mathematical curve or surface. In fact, many of these interaction techniques are examples of parameter manipulations or can be implemented this way. Unfortunately, the specification of parametrized graphics requires the algorithmic specification of dependencies on parameters; thus, some kind of programming language is necessary in order to formally describe parametrized graphics. In this work, we exploit the semantic power of Mathematica expressions, in particular those representing Mathematica graphics, to specify parametrized graphics, and employ the applet LiveGraphics3D to display specific instances of such graphics and interactively manipulate their parameters. Using Mathematica expressions allows us to generate, manipulate, and process these graphics within Mathematica; that is, Mathematica becomes our generic tool for parametrized graphics. With the help of two advanced examples, we demonstrate how to use Mathematica efficiently for this purpose.

Although interactive computer graphics are extremely popular, the programming of this is in general laborious and requires particular programming skills, e.g. DirectX3D, OpenGL, or Java3D programming, handling of events produced by a VRML or X3D scene graph in Java or ECMAScript, etc. On the other hand there are several examples of frameworks for particular interactive graphics which do not require such skills. Specifically, systems for the creation of and interaction with geometric constructions, e.g. Cabri Geometry, Geometer's Sketchpad, or Cinderella, demonstrate that the design of complex interactive graphics does not necessarily require costly programming. This simplicity is achieved by restricting the user-interaction to very few possibilities, in particular the positioning of points, and at the same time restricting the computer reaction to the calculation of a solution of a system of previously specified geometric constraints. While this scheme is sufficient for many applications, the geometric constraints limit it to a small class of graphics. Unfortunately, systems of more general constraints are considerably more complicated to solve, i.e. in general they are inappropriate for real-time interactive graphics.

Therefore the approach presented in this paper replaces constraints by dependencies, i.e. the modification of a parameter does not require the computation of a solution of a system of constraints but only the evaluation of a system of dependencies. Thus, there is no need to restrict the dependencies to geometric constraints. In fact, arbitrary algorithmic dependencies are possible; however, the specification of dependencies is strongly limited in this work in order to facilitate their fast evaluation. By defining these dependencies in a subset of the Mathematica language, it is possible to integrate them seamlessly into the definition of Mathematica graphics. These may be generated, manipulated, and displayed within the powerful Mathematica system. Interactive manipulation of parameters may be accomplished by displaying parametrized Mathematica graphics with the Java applet LiveGraphics3D, which is briefly described below. Two examples of nontrivial parametrized graphics are discussed in order to show that the limitations of LiveGraphics3D are in fact acceptable and to illustrate several useful techniques for the construction of parametrized graphics with Mathematica.

Parametrized Mathematica Graphics: An Example

The specification of parametrized graphics requires the specification of mathematical expressions; therefore, Mathematica's Graphics3D objects are almost perfect containers for parametrized graphics. This concept will be demonstrated with a simple example consisting of one Line and two Point primitives. The following scene describes a line segment between the point {0,0,0} and a parametrized point {x,y,z} together with the midpoint {x/2,y/2,z/2} of the line.

scene = 
        Graphics3D[{Line[{{0, 0, 0}, {x, y, z}}], PointSize[0.05], 
            Point[{x, y, z}], PointSize[0.03], 
            Point[{x/2, y/2, z/2}]}];

In order to show parametrized graphics we have to supply numeric values for all parameters. This is easily done with replacement rules. The parameters are called "independent variables" in contrast to "dependent variables", which will be introduced in the next subsection. The initialization rules may be applied with the ReplaceAll function. As dependent variables will require a slightly more complicated initialization, we hold off on this for the moment.

Dependent Variables

It is often useful to introduce abbreviations for particular (sub)expressions. For example, the coordinates of the midpoint {x/2,y/2,z/2} could be denoted by {mx,my,mz}. The abbreviations are termed dependent variables because their values may depend on the values of other variables. In this case, the construction of our example is:

scene = 
        Graphics3D[{Line[{{0, 0, 0}, {x, y, z}}], PointSize[0.05], 
            Point[{x, y, z}], PointSize[0.03], 
            Point[{mx, my, mz}]}];
independentVariables = {x -> 3, y -> 2, 
          z -> 1};
dependentVariables = {a -> x/2, mx -> a, my -> y/2, 
          mz -> z/2};

We can evaluate and show this scene by applying the replacement rules for abbreviations (dependent variables) and parameters (independent variables). Because dependent variables may also depend on other dependent variables we use a more powerful form of rule replacement via ReplaceRepeated. For example:

Show[
        scene //.  Join[independentVariables, 
            dependentVariables]];

Constrained Independent Variables

Sometimes it is useful to constrain the values of independent variables. For example, we might want to guarantee that the point {x,y,z} is always on a unit circle around the point {0,0,0} within the x-z-plane. We may enforce this by dividing x and z by Sqrt[x^2+z^2] and setting y to 0. These assignments may be included in the list of dependent variables.

dependentVariables = {length -> Sqrt[x^2 + z^2], 
          x -> x/length, y -> 0, z -> z/length, 
          mx -> x/2, my -> y/2, mz -> z/2};

To avoid an infinite loop from repeated replacement we have to apply the initialization rules for the independent variables first as below.

constrainedIndependentVariables  = 
        Map[#[[1]] -> (#[[1]] //. 
                  Map[#[[1]] -> (#[[2]] /. 
                            N[independentVariables]) &, 
                    dependentVariables]) &, 
          independentVariables];
Show[
        scene //.  Join[constrainedIndependentVariables, 
            dependentVariables]];

Direct Manipulation of Parametrized Graphics with LiveGraphics3D

In graphical user interfaces direct manipulation of numerical parameters is usually accomplished with particular widgets, e.g. sliders, scroll bars, or dials. However, the most "direct" way of manipulating a parameter that specifies the coordinate of  a geometric point is probably to move the point with a pointing device and thereby to modify the values of the parameters corresponding to the coordinates of that point. This technique allows users to explore high-dimensional parameter spaces simply by moving a few points.

The concept was implemented in LiveGraphics3D and presented in the talk Direct Manipulation of Parametrized Graphics at the 2001 Mathematica Developer Conference. LiveGraphics3D is a Java 1.1 applet that was primarily developed to display three-dimensional Mathematica graphics in HTML pages.  The URL of the homepage of LiveGraphics3D, which is free for non–commercial use, is http://wwwvis.informatik.uni-stuttgart.de/~kraus/ LiveGraphics3D/. Only a web browser with Java support is necessary in order to view the examples of parametrized graphics found on the homepage of LiveGraphics3D. However, employing LiveGraphics3D for your own Mathematica graphics requires additional efforts. This section offers a very brief overview of the steps required to display parametrized Mathematica graphics in HTML pages with LiveGraphics3D; a more detailed explanation is given in the documentation of LiveGraphics3D.

Calling LiveGraphics3D for Graphics Without Parameters

Firstly, the case of Mathematica graphics without parameters is discussed. Here is an example of an HTML page that calls the applet LiveGraphics3D.

<HTML>
<APPLET ARCHIVE="live.jar" CODE="Live.class" WIDTH=200 HEIGHT=200>
<PARAM NAME="INPUT_FILE" VALUE="test.m">
</APPLET>
</HTML>

The attribute ARCHIVE="live.jar"  refers to the Java archive live.jar, which has to be located in the same directory as the HTML file and may be downloaded from the LiveGraphics3D homepage. The parameter INPUT_FILE specifies another file called test.m, which should also be located in the same directory and has to contain a Mathematica Graphics3D expression in plain InputForm without any arithmetic expressions. This format may be generated by applying the functions InputForm and N.

InputForm[N[g = Graphics3D[{Line[{{0, 0, 0}, {1, 2, 3}}]}]]]

This form can be written to the file test.m with WriteString.

WriteString["test.m", ToString[InputForm[N[g]]]]; 
    Close["test.m"];

Instead of using  InputForm and WriteString directly, it is often more convenient to employ the functions LiveForm and WriteLiveForm, which are defined in the documentation of LiveGraphics3D. They are more general and produce smaller outputs.

Calling LiveGraphics3D for Parametrized Graphics

For parametrized graphics, the InputForms of the rules for the dependent and independent variables have to be specified with the parameters DEPENDENT_VARIABLES and INDEPENDENT_VARIABLES. For our first example the applet call could be:

<APPLET ARCHIVE="live.jar" CODE="Live.class" WIDTH=200 HEIGHT=200>
<PARAM NAME="INPUT_FILE" VALUE="test.m">
<PARAM NAME="INDEPENDENT_VARIABLES" VALUE="{x -> 3., y -> 2., z -> 1.}">
<PARAM NAME="DEPENDENT_VARIABLES" VALUE="{mx -> 0.5*x, my -> 0.5*y, mz -> 0.5*z}">
</APPLET>

The file test.m may again be written with the command from above or with WriteLiveForm.The parameters will supply LiveGraphics3D with all the information required for an initial evaluation of the parametrized graphics and the scene will be displayed. In this example only the primitive for the point  {x,y,z} may be moved to another position by the user, as only points with coordinates directly determined by independent variables may be manipulated. While the user moves the point, LiveGraphics3D constantly updates the values of the independent variables x, y, and z in order to reflect the new position of the point. Of course, all other expressions in the parametrized graphics have to be re-evaluated for the new values of these independent variables. Therefore, the Line primitive and the other Point will also change their positions as the user interacts with the "control" point. The example may be found at http://wwwvis.informatik.uni-stuttgart.de/~kraus/LiveGraphics3D/examples/parametrized/. The page also links to several other examples of parametrized graphics displayed by LiveGraphics3D. A web browser with Java support is necessary to view them.

Restrictions on Mathematica Expressions in LiveGraphics3D

Unfortunately LiveGraphics3D cannot evaluate arbitrary Mathematica expressions. In particular, only real numbers are allowed and composite expressions are only allowed instead of coordinates, i.e. within primitives, but not around primitives or within directives or options. Within these restrictions, LiveGraphics3D is able to evaluate several Mathematica operators, functions for basic arithmetics, most numerical and elementary functions, and a few factorial-related functions. Moreover, several non-mathematical functions are supported, in particular logical expressions, If, Which, and Switch. It should be emphasized that these limitations only pertain to parametrized Mathematica graphics that are displayed by LiveGraphics3D. They are not relevant for the generation of such graphics within Mathematica as long as the resulting graphics objects comply with them. The full set of symbols supported by LiveGraphics3D (e.g. for addition, multiplication), along with operator precedence, are provided in the documentation. Other mathematical documented LiveGraphics3D functionality includes mathematical constants known to LiveGraphics3D (along with their real approximations) and several common math and logical functions of the sort noted above.

Constructing Parametrized Graphics in Mathematica

This section presents two examples for the construction of parametrized graphics in Mathematica. The graphics are constructed to be efficiently displayed by LiveGraphics3D. Many more examples can be found on the homepage of LiveGraphics3D at http://wwwvis.informatik.uni-stuttgart.de/~kraus/LiveGraphics3D/examples.html.

A Parametrized Spirograph

This example demonstrates the construction of a parametrized spirograph. Additionally, parametrized animations are introduced and the presentation of two-dimensional graphics with LiveGraphics3D is discussed. The example is based on the Mathematica demo notebook "Spirographs with Mathematica", which may be found in the help browser of Mathematica 4 under "Getting Started/Demos>Demos>Spirograph" or simply by searching for "spirograph". This demo describes a spirograph as follows.

Imagine a wheel rolling around a second wheel that is rolling around another wheel and so on. A point on the rim of the outermost wheel will trace an interesting curve in the plane. Let the radius and angular frequency of the (j^th) wheel be (Subscript[r, j]) and (Subscript[n, j]). The point will be at the position (∑_(j = 1)^m)(Subscript[r, j]) (e^(i (Subscript[n, j])φ)) in the complex φ-plane. The function Spirograph generates a picture of the path of the point. Note that we cannot use the function ParametricPlot because it produces two-dimensional plot that must not contain unevaluated expressions.

Spirograph[f_, φ_, opts___] := 
        Graphics3D[
          Line[Table[{Re[ComplexExpand[f]], Im[ComplexExpand[f]], 
                0}, {φ, 0, 2 π, 2  π/50}]], opts, 
          PlotRange -> All, Boxed -> False, 
          ViewPoint -> {0, 0, 1}, 
          ViewVertical -> {0, 1, 0}];

The ComplexExpand is necessary as LiveGraphics3D cannot perform complex arithmetic. Also note that LiveGraphics3D cannot process two-dimensional graphics; therefore, a Graphics3D object is generated with all z coordinates set to 0 and an appropriate setting of the ViewPoint and ViewVertical options. Here is an example of a spirograph.

Show[
        Spirograph[(∑_(j = 1)^3) ((E^(j I  φ))/(j + 1)), φ]];

In order to understand the role of the +1 in the denominator, we will replace it by a parameter t.

scene = 
        Spirograph[(∑_(j = 1)^3) ((E^(j I  φ))/(j + t)), φ];
Show[scene /. {t -> -0.2}];

Within Mathematica we could animate this curve with the help of the Animate command in the Graphics`Animation` package. In order to display this parametrized animation with LiveGraphics3D, we save the graphics object with WriteLiveForm to a file called spirograph.m.

WriteLiveForm["spirograph.m", scene, {t, -0.9, 2, 0.02}, 
      AnimationDirection -> ForwardBackward]

WriteLiveForm (and LiveFrom) identify a parametrized animation by the list of four elements in the third argument. Note that only the parametrized Graphics3D object is saved, instead of a list of Graphics3D objects with specific values for t. An appropriate applet call  would be:

<APPLET ARCHIVE="live.jar" CODE="Live.class" WIDTH=200 HEIGHT=200>
<PARAM NAME="INPUT_FILE" VALUE="spirograph.m">
<PARAM NAME="INDEPENDENT_VARIABLES" VALUE="{t -> -0.2}">
<PARAM NAME="MOUSE_DRAG_ACTION" VALUE="NONE">
</APPLET>

The parameter MOUSE_DRAG_ACTION is set to NONE in order to avoid three-dimensional rotation of this two-dimensional curve. Within LiveGraphics3D the animation is stopped (and restarted) by a double click with the left mouse button. By holding down the ALT key and the left mouse button (or alternatively just the right mouse button) and moving the mouse horizontally, the animation parameter may be manipulated directly.

Shortest Path on a Sphere

The goal of the second example is to construct the shortest path between two user-specified points {ax,ay,az} and {bx,by,bz} on a sphere, e.g. a unit sphere around {0,0,0}. The construction is not too complicated since this path is always a segment of a great circle. The coordinates of the points {ax,ay,az} and {bx,by,bz} are parameters of this scene, i.e. the independent variables. However, they are constrained to the surface of the sphere, i.e.  the vectors {ax,ay,az} and {bx,by,bz} have to be divided by their lengths. Within Mathematica it is much more convenient to work with two vectors a={ax,ay,az} and b={bx,by,bz} instead of six coordinates. However, the result has to be given in coordinates for LiveGraphics3D. We will use dot products, Thread, and exploit the "listability" of multiplication and division to produce rules for all three coordinates of a vector. Further, in order to construct the shortest path, we will need the angle between a and b, which is ArcCos[(a.b)/aLength/bLength]. For this we require a point on the great circle through a and b that is one quarter of the circumference away from a. The direction of this vector c={cx,cy,cz} may be computed as Cross[Cross[a,b],a]. The normalized c will be denoted by d={dx,dy,dz}.  Thus our definition of dependentVariables is:

independentVariables = {ax -> 0, ay -> -2, 
          az -> 0, bx -> 1, by -> 0, 
          bz -> 1};
a = {ax, ay, az}; b = {bx, by, bz}; c = {cx, cy, cz}; 
    d = {dx, dy, dz};
(dependentVariables = 
          Flatten[
{aLength -> Sqrt[a . a], 
              bLength -> Sqrt[b . b], 
angle -> 
                ArcCos[(a . b)/aLength/
                    bLength], 
Thread[a -> a/aLength], 
              Thread[b -> b/bLength], 
Thread[
                c -> 
                  Cross[Cross[a, b], a]], 
cLength -> 
                Sqrt[c . c], Thread[d -> c/cLength]}]);

Note that there is only one rule for each variable in dependentVariables as a second rule would be ignored by Mathematica but evaluated by LiveGraphics3D, which evaluates rules sequentially as if they were assignments. For this reason the order of rules is also crucial. For example, the rule for dx depends on the values of cx and cLength; thus, the rules for cx and cLength should precede it in order to be evaluated by before dx is evaluated. Since our independent variables are constrained, we have to apply the rules for dependent variables to their initial values as mentioned above.

constrainedIndependentVariables  = 
        Map[#[[1]] -> (#[[1]] //. 
                  Map[#[[1]] -> (#[[2]] /. 
                            N[independentVariables]) &, 
                    dependentVariables]) &, 
          independentVariables];

The shortest path may now be constructed as a sequence of lines, which are computed by a linear combination of the vectors a and d.We can add any static graphics to this parametrized graphics; in particular, we will include a grid representing the sphere.

ni = 20; 
    path = Line[
        Table[Cos[angle*i/ni] a + Sin[angle*i/ni]*d, {i, 0, 
            ni}]];
sphere = {Table[
            Line[Table[{Sin[theta] Cos[phi], Sin[theta] Sin[phi], 
                  Cos[theta]}, {theta, 0, Pi, Pi/16}]], {phi, 0, 2  Pi, 
              2  Pi/16}], 
          Table[Line[
              Table[{Sin[theta] Cos[phi], Sin[theta] Sin[phi], 
                  Cos[theta]}, {phi, 0, 2  Pi, 2  Pi/16}]], {theta, 0, Pi, 
              Pi/16}]};

The final scene should also include two Point primitives at a and b and some directives and options; thus, the final Graphics3D object is:

scene = 
        Graphics3D[{PointSize[0.03], Point[a], Point[b], 
            AbsoluteThickness[0.5], sphere, Thickness[0.02], path} , 
          Boxed -> False];
Show[
        scene //. Join[constrainedIndependentVariables, 
            dependentVariables]];

In order to view this scene with LiveGraphics3D, this applet call could be used.

<APPLET ARCHIVE="live.jar" CODE="Live.class" WIDTH=200 HEIGHT=200>
<PARAM NAME="INPUT_FILE" VALUE="shortestpath.m">
<PARAM NAME="INDEPENDENT_VARIABLES" 
VALUE="{ax -> 0, ay -> -2, az -> 0, bx -> 1, by -> 0, bz -> 1}">
<PARAM NAME="DEPENDENT_VARIABLES" VALUE="{aLength -> Sqrt[ax^2 + ay^2 + az^2], 
 bLength -> Sqrt[bx^2 + by^2 + bz^2], angle -> ArcCos[(ax*bx + ay*by + az*bz)/(aLength*bLength)], 
 ax -> ax/aLength, ay -> ay/aLength, az -> az/aLength, 
 bx -> bx/bLength, by -> by/bLength, bz -> bz/bLength, cx -> ay^2*bx + az^2*bx - ax*ay*by - ax*az*bz, 
 cy -> -(ax*ay*bx) + ax^2*by + az^2*by - ay*az*bz, cz -> -(ax*az*bx) - ay*az*by + ax^2*bz + ay^2*bz, 
 cLength ->Sqrt[cx^2 + cy^2 + cz^2], dx -> cx/cLength, dy -> cy/cLength, dz -> cz/cLength}">
</APPLET>

Future Work and Conclusions

LiveGraphics3D is still under development. With respect to parametrized graphics, there are several possibilities for improvements; in particular, the parametrization of directives appears to be one of the most interesting future extensions. Further improvements include support for complex numbers and more Mathematica functions. Moreover, lighted parametrized polygons would greatly benefit from repeated computations of their colors.

Parametrized Mathematica graphics are an exciting concept, which is consistently based on Mathematica expressions, and therefore allows users to exploit the full power of Mathematica for the design of parametrized graphics for presentations, illustrations, visualizations, animations, explorations, virtual experiments, etc. in publications, online services, course-ware, textbooks, encyclopedia, etc. As discussed, LiveGraphics3D allows users to interact with these parametrized graphics in a very intuitive and convenient way. Since LiveGraphics3D is a Java 1.1 applet, it may be used on web pages, CD-ROMs, or in Mathematica notebooks (via J/Link). Of course, this technique is not limited to mathematical content, but may rather lead to interactive schematic illustrations of any kind, and might even result in works of art.

Acknowledgments: Thanks to Rüdiger Dietrich, Robin Lehmann, Lars Schäfer, and Dean Simec, who have implemented a first version of the parser and evaluator for Mathematica expressions in Java. Many thanks also to Eric Weisstein, Maurice Starck, Hidekazu Takahashi, Thomas Ertl, Marcelo Magallon, Todd Gayley and Tom Wickham-Jones for valuable comments and discussions. Special thanks to Daniel Lichtblau for organizing the Mathematica sessions at SCI2002.