Page 1: Transformations as Math vs. Code

CS559 Spring 2021 Sample Solution - Workbook 4

Written by CS559 course staff

You can try out the example solutions here. The interesting code is on page 4 and page 5.

When working with Canvas, we write lots of code that refers to the positions of points using things such as context.moveTo(x,y), context.lineTo(x,y) or context.fillRect(x,y,w,h). In these cases, we pass points as a pair of numbers (x,y).

When thinking about points, it is easier notation to write points directly. So we can use a variable p to refer to a point. In terms of implementation, we might represent p as an array (of length 2 for 2D), or as an object with members for x and y. Some APIs we will see later in the class will define their functions to take point objects, rather than a list of individual parameters.

Points and vectors are not the same (see CS559 Tutorial: Points, Vectors, Coordinate Systems) if you need a reminder). However, in code (and notation), we often do not distinguish between them. In terms of representation, they store the same things (e.g., two numbers for a 2D point or a 2D vector).

Generally, we write vectors or points as lowercase boldface (in print). We will try to be consistent with that. So, x is a scalar (number), x is a vector, and $x_x$ is the x component of the x vector (which is a scalar). It might be more correct to write $ \mathbf{x}_x $ since x is a vector.

And a warning, you will see things x, x, $ x $ and $ \mathbf x $. Sorry for the inconsistency in typesetting - getting math right on the web is a bit of a hassle. In text variables will be x (scalar) or x (vector), in equations (that may appear inline), they will be $ x $ (scalar) or $\mathbf x $ (vector).

Transformations as Functions

Recall that we said that transformations are functions that change points into other points. So, for example when we apply a translation translate(a,b) we are saying to use the function $ f(x,y) = (x+a, y+b) $ on every point we encounter.

Using vector notion (having the point be a vector variable), we could instead write this as translate(t) (for a vector t) is $ f(\mathbf{x})=\mathbf{x}+\mathbf{t} $. If we were being picky about notation, the f should also be boldfaced since it is a function that returns a vector.

The other transformations we have seen so far can also be written this way (as functions that take a point as input and produce a point as output). In fact, this might be a way to define transformation: it is a function that takes a point as input and returns a new point as output.

The only thing new here is a change of notation: we are writing $ f(\mathbf x) $ rather than $ f(x,y) $. This makes it easier to write/type the math. And it also makes it easier to connect between what we see in the textbook and what we write as code.

Transformation Composition as Function Composition

In the previous workbook, we saw how we can use sequences of transformations to create one transformation that does a compound thing. For example, in order to scale about a particular point, we translate such that the center point is at the origin, we scale by the desired amount, and then we translate to return the center point from where it came. In code, this sequence would be written:

1
2
3
4
context.translate(c.x, c.y);
context.scale(s,s);
context.translate(-c.x, -c.y);
DRAW STUFF

Where draw stuff includes drawing commands that provide points. Note that we have a point c, so in our Canvas code we have to refer to its specific parts.

If we write this using function notation, we first have the “last” translate (which moves the point c to the origin, translate(-c.x, -c.y)). Let’s call this function f, so the application of it to the points (in draw stuff) would be $ f ( \mathbf x ) $. Call the second function (that does the scaling) g. This function is applied to the results of applying the first function to the point. Similarly, if we call the final translation h, that function is applied to the result of the second function (which was applied to the results of the first function, which was applied to the point).

So, we could re-write the code in math as: $$ h ( g ( f ( \mathbf x))) $$

Notice that the first function we apply to a point (f) appears in the right of the list, while the last function we apply appears first. Just like it does in the code. We can think of the functions as a “machine” where we pour points in on the right, and they come out on the left. They go in their “local” coordinate system, and come out in the final coordinate system on the left.

Function notation also lets us talk about combining the functions. The idea of creating a new function by putting two functions together is called composition. If we want to create a new function that does what the combination of f and g do (apply f to the input, then apply g to the result), we write $ g \circ f $. Note that this new function first applies f to the input, but f is still on the right of the expression (it is closest to the input). Or, to define a new function k as the sequence above, $ k = h \circ g \circ f $, which means that $ k(\mathbf x)=h(g(f(\mathbf x))) $.

Understanding this is important since it helps explain the ordering. In code, points are “issued” at the bottom and move “up” through the transformations. In math notation, the points are on the right, and move through the transformations right to left. The transformations that are written last are applied to the points first.

If you’re wondering where the parameters to the transformation went (c and s in the code example), they were built in to the functions that we defined. So g above was “scale by s”. We could have picked a different notation, for example calling the scaling function S (capital), and using a subscript to denote its parameters.

$$ \mathbf{T}_{\mathbf{c}} ( \mathbf{S}_{\mathbf{s}} (\mathbf{T}_{\mathbf{-c}} (\mathbf{x}))) $$

Again, notice how this reads like the code (left to right), with the points we draw ($\mathbf{x}$) coming last.

Summary

Hopefully, representing points using vector notation and using function notation for transformations connects to the code for you. This kind of notation will make many things easier going forward.

We’ll use this notation to connect what we’re doing to linear algebra on Page  2  (Linear, Affine, Projective).

There are no points associated with this page.