Dynamic Text and Linking MathObjects

The method setLatex() of the LatexMathObject allows to change and recompile the LaTeX code, but there is another way to add text that changes its content while animating, using the Link class. Let's see this with an example. Suppose you have the following code in the runSketch() method, that rotates a red point along the unit circumference:

def A = Point.at(1, 0)
    .thickness(30)
    .drawColor("red")
play.rotate(5, Vec.origin(), 2*PI, A)

Suppose you want to show the coordinates of the point while the point moves. This can be accomplished advancing each frame and doing the proper changes to the LatexMathObject:

//The format I will use to represent the coordinates.
//2 decimal places. Use point as decimal separator
def df = new DecimalFormat("0.00")

def A = Point.at(1, 0)
        .thickness(60)
        .drawColor("red")
def anim = Commands.rotate(5, Point.origin(), 2 * PI, A)

def text = LatexMathObject.make(r"$(1,0)$", AnchorType.UPPER_AND_ALIGNED_LEFT)

//Put the text in the upper left screen corner
text.stack().withGaps(.1, .1).toScreen(ScreenAnchor.UPPER_LEFT)
scene.add(
        Shape.circle().drawColor('darkgray'),
        Shape.segment(Vec.origin(), A).drawColor('cornflowerblue'),
        text
)

anim.initialize()
while (!anim.processAnimation()) {//Main animation loop
    //Update the text with the new coordinates
    text.setLatex(r"$(" + df.format(A.v.x) + ", " + df.format(A.v.y)+ r")$")
    scene.advanceFrame()
}

You will have the following animation:

01_dynamic

We will see another way to get this effect, using the Linkclass

Linking objects

A link is a method that is called immediately after the objects have been updated with the update() method and prior to render them. Basically, it gets an attribute of the "from" object and puts it in the "destiny" object.

We illustrate this with an example:

import java.text.DecimalFormat

def A = Point.at(1, 0)
        .thickness(60)
        .drawColor("red")

def text = LatexMathObject.make(r "$({#0},{#1})$")

text.setDefaultArgumentFormat("0.00")



//Ok, time to link some objects...
scene.registerLink(A, //From object A...
        LinkType.X, //...take the X coordinate...
        text, //and put it in the object text...
        LinkType.ARG0 //in its first argument
)

scene.registerLink(A, //From object A...
        LinkType.Y, //...take the Y coordinate...
        text, //and put it in the object text...
        LinkType.ARG1 //in its second argument
)

//...rest of the code...

//You can rotate the point directly without manually advancing frames
play.rotate(5, Vec.origin(), 2 * PI, A)

If you execute this code you will get the same result as before. Lets see what code we used. Look at the LaTeX code in the LatexMathObject:

def text = LatexMathObject.make(r"$({#0},{#1})$")

The coordinates have now been replaced by the strings {#0} and {#1}. These are special escape strings that instruct JMathAnim to replace them with the values of the first and second arguments, respectively. In fact, a LatexMathObject can hold up to ten arguments, named {#0} to {#9}. With the method text.setDefaultArguments() you can set how the number will be formattted. You can pass a String like "0.00" for example or a DecimalFormat object.
You can also set individual formats for arguments, for example:

text.setArgumentFormat(0,new DecimalFormat("0.0"))//The #0 argument will have this format
text.setArgumentFormat(1,new DecimalFormat("0.000"))//The #1 argument will have this format

The set of this argument is done via the linking process. To do so, we must create and register a link in the scene flow. This is done with this command:

scene.registerLink(A, //From object A...
    LinkType.X, //...take the X coordinate...
    text, //and put it in the object text...
    LinkType.ARG0 //in its first argument
)

The comments tell how it works. The first parameter is the source object, where to extract the information. The second parameter is a LinkType enum that defines the type of information. Depending on the object type and this value a certain value is extracted, and JMathAnim do its best to extract the appropriate information. For example in this case, X coordinate of the point is extracted. If A were a MathObjectGroupfor example, the x coordinate of the center of the object will be extracted.

The third and fourth parameters define the destiny object and the type of attribute to change in this object. In this case the value ARG0 means to change the value of the first argument.

Currently, the following LinkType values are supported:

  public enum LinkType {
      X, Y, //Coordinates of a Point or the center of a MathObject
      VALUE, //If a vector, returns its norm. If a Mathobject, the distance from the origin to its center
      COUNT, //If a MathObjectGroup, returns the number of elements. If Shape, number of points
      WIDTH, HEIGHT, XMIN, XMAX, YMIN, YMAX,//Return these values from the Bounding Box of the object
      ARG0, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9 //Arguments of a LatexMathObject
    };