# Coordinates

Punctual let’s you direct access to fragment coordinates, both in Cartesian and polar systems. This feature allows for a lot creative possibilities.

This section is intimately related with Geometric transformations especially the `setfx`

, `setfy`

and `setfxy`

functions. Also, some examples use Oscillators.

## Cartesian coordinates

The Cartesian coordinate system is the coordinate system most commonly used, where a point in the plane is identified by its horizontal distance and vertical distance to a reference point called origin. These two values are called coordinates, the horizontal axis is called x-axis, and the vertical one y-axis. See Coordinate system to see the details on how this is implemented in Punctual.

`fx`

, `fy`

, `fxy`

As explained in fragments, Punctual expressions are evaluated for each fragment. For a given fragment, `fx`

is the x-coordinate of that fragment, `fy`

is the y-coordinate, and `fxy`

is a list with both coordinates.

The next examples are some creative ideas one can explore using only coordinates and basic mathematical functions.

Dividing the screen in 10 vertical gradients:

```
5 * (fx % 0.2) >> add;
```

The modulus `fx % 0.2`

(see mathematical functions for more information) makes 10 stripes from 0 to 0.2 (10 as `fx`

goes from -1 to 1). Then, we multiply by 5 to rescale the value to a 0 to 1 range.

### Color patterns

Here we are using three simple formulas to get each of the three RGB channels directly from the coordinates of each fragment.

```
-- Try changing abs by unipolar
abs [fx, (-1)*fy, (fx+fy)/2] >> add;
```

```
unipolar $ (-1)*fx++fxy >> add;
```

```
[unipolar $ sin' fx, 1 - abs fy, unipolar $cos fx] >> add;
```

There are a lot of formulas that allow you to make cool gradients as a starting point for more complex transformations.

See Colors for some ideas on using other colors spaces aside from RGB.

### Using punctual to draw mathematical functions:

A typical mathematical function has the form `y=f(x)`

, where `f(x)`

is a formula that specifies how to get the `y`

coordinate from the `x`

coordinate. So, for any `x`

, we draw a point at coordinates `(x, f(x))`

.

Using this method we can draw a lot of mathematical functions (here, the `zoom`

is only used to see a bit more of the resulting graph):

```
zoom 0.4 $ point [fx, cos fx] >> add;
```

```
zoom 0.4 $ point [fx, log $ abs fx] >> add;
```

```
zoom 0.4 $ point [fx, fx*fx] >> add;
```

Another way to do the same is by using the `between`

function (see Mathematical functions).

In essence, `between`

receives two values and a graph and returns 1 if the graph is between the two values, or else 0.

Remember that this is evaluated independently for each fragment, so in the next example, for any fragment `(fx,fy)`

we’ll draw white if and only if `fy`

is almost equal to `cos fx`

. The `2*px`

is the margin that `fy`

can be away from `cos y`

and still be white, and determines the wideness of the line we’ll draw. As explained a bit later, `px`

is the fragment’s height:

```
zoom 0.4 $ between [cos fx-2*py, cos fx+2*py] $ fy >> add;
```

We can use evolve these ideas to create interesting patterns:

```
point[fx, osc 0.09*cos (fx*fy*15*(2+osc 0.32))] >> add;
0.98 * fb fxy >> add;
```

`px`

, `py`

Depending on the screen resolution and the windows size, pixels on Punctual will have a specific dimensions expressed in the Punctual coordinate system.

You can access a pixel’s width with `px`

and a pixel’s height with `py`

. This is usually used to draw thin lines, as in the following example, or the ones on the previous section:

```
zoom 0.4 $ circle [fx, fx*fx] $ 4*px >> add;
```

`aspect`

, `fit`

`aspect`

is the ratio between the width and height of the window, so, if you don’t change the window size (or use `fit`

), it’s a constant.

To “see” it’s value, we can try something like this:

```
[0.3*aspect,0,0] >> add;
```

Now, change the window size, and you should see how the background is redder as the width height ratio increases, and darker as it decreases.

`fit`

can be used to rescale the x coordinates in order to change the aspect ratio of the result. When doing this, the visible coordinates on the x-axis no longer will be on the range -1 to 1 (unless `fit aspect`

is specified, which is the same as doing nothing).

The most obvious way of using `fit`

is to correct the aspect of geometric shapes, so a circle draws like a circle, and so on:

```
fit 1 $ circle 0 0.3 >> add;
```

```
fit 1 $ rect 0 0.5 >> add;
```

Another useful application of `fit`

is to scale an external source (an image, a video, or the camera output) to fit the screen, or a particular portion of the screen:

```
fit (0.5*aspect) $ move [1, 0] $ img "https://upload.wikimedia.org/wikipedia/commons/d/d4/Karl_Marx_001.jpg" >> add;
fit (0.5*aspect) $ move [-1,0] $ img "https://upload.wikimedia.org/wikipedia/commons/2/21/Friedrich_Engels_portrait_%28cropped%29.jpg" >> add;
```

In this example, we took images of the Communist Manifesto authors from Wikicommons, and made each one of them to occupy the half of the window, independently from its size.

Same idea, but we divide the window in two horizontally:

```
fit (2*aspect) $ move [0,-1] $ img "https://upload.wikimedia.org/wikipedia/commons/8/87/Tundra_in_Siberia.jpg" >> add;
fit (2*aspect) $ move [0,1] $ img "https://upload.wikimedia.org/wikipedia/commons/2/2d/Picea_glauca_taiga.jpg" >> add;
```

Can we combine both previous examples to divide the window in four equal-sized parts? The answer is yes, as `aspect`

is modified just when `fit`

is executed:

```
fit (0.5*aspect) $ fit (2*aspect) $ move [-1,1] $ img "https://upload.wikimedia.org/wikipedia/commons/2/2d/Picea_glauca_taiga.jpg" >> add;
```

Now, these last examples show the most standard uses of `fit`

, but you can also use it in many creative ways.

For example, we can apply an oscillator to the aspect ratio to deform the image periodically:

```
fit (osc 0.2) $ circle 0 0.8 >> add;
```

Now, evolving this example, we can create beautiful patterns:

```
spin [saw 0.2, (-1)*saw 0.2] $ fit (8*osc (0.5*cps)) $ tile [4,step [1,4,8,16] $ saw cps] $ circle 0 0.8 * [0.8,0,0.8]>> add;
0.8 * fb fxy >> add;
```

Here, we are synchronizing the `fit`

oscillator to the beat, and increasing its range to -8 to 8. We are also drawing a lot more circles using `tile`

. The replication over the y-axis changes over time, due to the use of `step`

and the `saw`

oscillator. Finally, the `spin`

with to graphs as first argument, duplicates the whole set and made each of the copies rotate in opposite directions.

## Polar coordinates

In the polar coordinate system, each point in the plane also has two coordinates, but they are the distance to the *pole* (the center of the window, analogous to the origin in Cartesian coordinates), and the angle from the horizontal ray that goes from the pole to the right (called *polar axis*), measured in radians.

`fr`

, `ft`

, `frt`

In the same way that `fx`

, `fy`

and `fxy`

allow to get fragment coordinates in the Cartesian system, `fr`

, `ft`

and `frt`

are the fragment coordinates in the polar system.

`fr`

is the distance from the pole, and is equivalent to `dist 0`

or `dist [0,0]`

.

Note that if we only move through one of the axis, `fr`

goes from 0 to 1, but can be larger. The point at `[1,1]`

has a `fr`

of approximately 1.41, that is the square root of 2 (by the Pythagorean theorem).

`ft`

is the angle from the reference ray, which is the right part of the horizontal axis. In Punctual, this angle goes from -π to π radians. This is important, as many times you’d like to rescale this range to a [-1,1] range or [0,1] range, in order to use it in other parts of your code:

- To a [-1,1] range:
`ft/pi`

. - To a [0,1] range:
`linlin [(-1)*pi, pi] [0,1] ft`

or`unipolar $ ft/pi`

.

Next examples are similar to the ones of the Cartesian coordinates section, but the result can be quite different when using polar coordinates.

20 radial gradients:

```
fit 1 $ 10/pi*(ft % (pi*0.1)) >> add;
```

Or concentric gradients:

```
fit 1 $ 10 * (fr % 0.1) >> add;
```

Color patterns:

```
r << fr/1.4;
t << ft/pi;
[1-r, abs t, abs $ r/ft] >> add;
```

```
r << fr/1.4;
t << ft/pi;
[1-r, abs t, abs $ fx*fy] >> add;
```

Note how `fr`

and `ft`

are rescaled to keep the red and green coordinates from 0 to 1.

Mathematical functions:

Not so obvious as with Cartesian coordinates, but it’s possible to build interesting shapes using the same ideas:

```
fit 1 $ point [fx, sin' ft] >> add;
```

For each fragment, draw only the points where y matches the sine of the angle. This results in a circumference of radius 1 (by definition of the sine function, the sine of an angle is the y coordinate of the corresponding point on the circumference of radius 1), and a line at `x=0`

, as the sine of 0 (or π) is 0.

The missing central part of the line is due to rounding errors. Actually, `point`

is a small `circle`

, so it’s visible if some fragment is near enough the specified coordinates. That explain why the circumference has some wideness. Now, as we get closer to the origin, a little change in coordinates radically changes the angle, and that’s why there isn’t any point there which sine is near enough to the y coordinate.

Similarly: `fit 1 $ between [sin' ft - py, sin' ft + py] $ fy >> add;`

.

`dist`

, `prox`

`dist`

is the distance of a fragment to a given position.

`prox`

is the opposite of `dist`

, the idea of proximity of a fragment to a given position. `prox`

is calculate such as two opposite screen points have a proximity of 0, and one point has a proximity of 1 to itself.

Let’s take for example [1,1] and [-1,-1] as two point that are as far away from each other as it is possible in the initial visible screen. The distance between them, per the Pythagorean theorem, is the square root of 8, that is approximately 2.828427. `prox`

is computed as (2.828427-dist[x,y])/2.828427, clamped to be between 0 and 1.

One very usual way of using `prox`

is to create masks. Visuals can get quite bright easily, and this can make it difficult for you or the people you are jamming with to see the code on the screen.

You can create a mask in order to keep the borders of the screen relatively clear and focus the visuals on the center:

```
a << 1;
m << prox 0 ** 4;
a*:m >> add;
```

Here, `a`

is the annoying graph, in this case a completely white screen. `m`

is the mask, calculated as the proximity to the origin, and raised to the power of 4.

Note that, as all proximities lies between 0 and 1, as we increase the power, the resulting numbers will be nearer to 0.

Finally, we multiply `a`

and `m`

, point to point, deeming each fragment according to the proximity it has to the center.

Following there are some examples on how can we use `dist`

and `prox`

in different creative ways:

- Color patterns depending on the distance of each fragment to certain coordinates:

```
[dist [0.5,0], prox [-0.6,-0.3], dist [-0.3,0.3]] >> add;
```

- Deform an image:

```
i1 << img "https://upload.wikimedia.org/wikipedia/commons/0/0c/Golden-eyed_tree_frog_%28Agalychnis_annae%29_1.jpg";
tile [prox [0.5,0], 3*dist [0,0.2]] $ i1 >> add;
```

Here we use `tile`

(see geometric transformations) to deform the image, as the value of tile is different for each fragment.

We can add some audioreactiveness (see audio reactive visuals) to the last pattern to make it a bit more interesting:

```
i1 << img "https://upload.wikimedia.org/wikipedia/commons/0/0c/Golden-eyed_tree_frog_%28Agalychnis_annae%29_1.jpg";
tile [prox [ihi,0], 3*dist [0,ilo]] $ i1 >> add;
```

## From Cartesian to polar and viceversa

There are a bunch of functions that are meant to transform coordinates from the Cartesian system to the polar system or viceversa:

`xyrt`

: from Cartesian to polar.

To understand this function let’s look at the following example:

```
c << [1,osc 0.1];
fit 1 $ [circle c 0.1, circle (xyrt c) 0.1] >> add;
```

The red circle stays at `x=1`

and moves vertically, from `y=-1`

to `y=1`

due to the oscillator.

The cyan circle is very similar, but we’ve applied `xyrt`

to its center coordinates. That means that these coordinates are transformed to polar coordinates. So, looking at the first circle and thinking in how this movement affects the angle and radius from the center, we see that the angle moves from `-pi/4`

to `pi/4`

, that is from approximately -0.79 to 0.79. The radius moves from the square root of two (1.41) at the top, then decreases until it get to 1, just on the horizontal axis, and then increases again to 1.41 at the bottom.

Now we take these two coordinates, but read them as Cartesian coordinates (note that `xyrt`

calculates the polar coordinates, but doesn’t apply any real geometric transformation like `setfxy`

does). So, the result is a circle which x coordinate moves from 1.41 to 1 then again to 1.41, and which y coordinate moves from -0.79 to 0.79.

Let’s add a few reference lines to check our calculations:

```
c << [1,osc 0.1];
fit 1 $ [circle c 0.1, circle (xyrt c) 0.1] >> add;
mono $ fit 1 $ hline [-0.79, 0.79] px >> add;
mono $ fit 1 $ vline [1,1.41] px >> add;
```

As a side note, see how the first example can be rewritten shorter using the `++`

operator from the combining graphs section:

```
c << [1,osc 0.1];
fit 1 $ circle (c++xyrt c) 0.1 >> add;
```

`xyr`

, `xyt`

These two functions are nearly identical to `xyrt`

, but they only return one of the two coordinates, the radius or the angle respectively.

Following the previous example:

```
c << [1,osc 0.1];
fit 1 $ [circle c 0.1, circle [xyr c,0] 0.1] >> add;
mono $ fit 1 $ vline [1,1.41] px >> add;
```

```
c << [1,osc 0.1];
fit 1 $ [circle c 0.1, circle [0,xyt c] 0.1] >> add;
mono $ fit 1 $ hline [-0.79, 0.79] px >> add;
```

`rtxy`

: from polar to Cartesian.

This is the opposite from `xyrt`

: it takes coordinates in the polar system and returns the equivalent in the Cartesian system.

```
c << [1,pi*osc 0.1];
fit 1 $ zoom 0.25 $ circle (c++rtxy c) 0.1 >> add;
```

The red circle keeps its x coordinate at 1 and oscillates between -π and π on the y coordinate (note the zoom in order to see all its movement).

The cyan circle takes the 1 as its distance from the origin, and changes the angle, so it keeps moving around the origin, always at the same distance.

I find that `rtxy`

is the most usable of the whole family to create cool visual effects.

In the next example, let’s start with this:

```
c << [[0.2,0.3..2]*:osc 0.12*osc 0.13, pi*osc 0.1*osc 0.11];
zoom 0.25 $ circle c 0.1 >> add;
```

These are a bunch of circles that move together in a somewhat irregular way due to the multiplications of oscillators at different frequencies.

The first bit (`[0.2,0.3..2]`

) uses Haskell style list expansion to create the x coordinate for each circle, from 0.2 to 2, going in steps of 0.1.

The y coordinate is common to all circles, and oscillates from -π to π.

Next step is just take all the circle’s center coordinates and read them as polar coordinates.

```
c << [[0.2,0.3..2]*:osc 0.12*osc 0.13, pi*osc 0.1*osc 0.11];
circle (rtxy c) 0.1 >> add;
```

Now, we apply some basic geometric transformations, using combinations of `fx`

, `fy`

, `ft`

and `fr`

to twist the circles geometry:

```
c << [[0.2,0.3..2]*:osc 0.12*osc 0.13, pi*osc 0.1*osc 0.11];
fit 1 $ spin (fr*4) $ move [ft*fx*0.3,ft*0.1] $ circle (rtxy c) 0.1 >> add;
```

Finally, let’s add some repetition in the middle to create more elements:

```
c << [[0.2,0.3..2]*:osc 0.12*osc 0.13, pi*osc 0.1*osc 0.11];
fit 1 $ spin (fr*4) $ tile [4,4] $ move [ft*fx*0.3,ft*0.1] $ circle (rtxy c) 0.1 >> add;
```

Playing with circles and polar coordinates is fun! In the last example, all the circles were moving like a whole. Can we make each one to move separately from the others?

Let’s start with our circles forming a bigger circumference around the center:

```
t << linlin [0,1] [0, 2*pi] [0, 0.02..1];
fit 1 $ circle (rtxy [0.5, t]) 0.1 >> add;
```

Here we use a list expansion for the circles angles, just like in the last example, and rescale it from a 0 to 1 range to a 0 to 2π using `linlin`

, just because it’s easier to think from 0 to 1.

Then draw all the circles using polar coordinates, at a fixed distance from the origin of 0.5.

Let’s made the circles spin:

```
t << linlin [0,1] [0, 2*pi] [0, 0.02..1];
o << pi * saw 0.1;
fit 1 $ circle (rtxy [0.5, t+:o]) 0.1 >> add;
```

Here, `o`

is an oscillator that goes from -π to π, and when it reaches π it starts again from -π. We add this oscillator to each angle, and the result is that all the circles spin together.

Finally, let’s apply an oscillator to the radius too, but this time, each circle will have a distinct frequency, so they will move apart from each other. We make this by using `t`

to modify the oscillator frequency in the bit `osc (0.1*t)`

.

Now, we have a list of radius and a list of angles, and we need to link them together: the first radius with the first angle, the second radius with the second angle, and so on. This is just what the `zip`

function from combining lists does.

As a final touch, we use `mono`

to combine all channels into one, which make all circles white:

```
t << linlin [0,1] [0, 2*pi] [0, 0.02..1];
o << pi * saw 0.1;
fit 1 $ mono $ circle (rtxy $ zip (osc (0.1*t)) (t+:o)) 0.1 >> add;
```

`rtx`

, `rty`

These two functions are nearly identical to `rtxy`

, but they only return one of the two coordinates, the x or y coordinate respectively.

```
r << unipolar $ osc 0.03;
t << pi*osc 0.07;
fit 1 $ circle [r,t] 0.1 >> add;
fit 1 $ circle (rtxy [r,t]) 0.1 >> red;
fit 1 $ circle [rtx [r,t], 0] 0.1 >> green;
fit 1 $ circle [0, rty [r,t]] 0.1 >> blue;
```

In this example, `r`

oscillates from 0 to 1, and `t`

from -π to π. There are a total of four circles:

- White:
`r`

and`t`

are interpreted as Cartesian coordinates x and y. - Red:
`r`

and`t`

are read as polar coordinates. - Green:
`r`

and`t`

are polar coordinates, but only used to calculate the resulting x position. - Blue: same as green, but only the y position is calculated.

## Examples

### 10 ways of drawing a circumference of radius 1

Just to see the flexibility of Punctual and different ways to use coordinates, let’s think of different ways to draw a circumference of radius 1.

Probably the easiest way: let’s paint white (1) all fragments whose radius is 1, pixel more, pixel less:

```
between [1-px, 1+px] $ fr >> add;
```

As the radius is no more than the distance to the origin, this is equivalent:

```
between [1-px, 1+px] $ dist 0 >> add;
```

Also, it’s possible to make this calculation explicit, using the Pythagorean theorem:

```
between [1-px, 1+px] $ sqrt $ fx*fx+fy*fy >> add;
```

Next is a similar approach, but without using `between`

. Here, on one hand we take all fragments whose radius is a bit lesser than one, and on the other the fragments whose radius is a bit greater than one. What we want is the intersection of those two, so we multiply the graphs (the result will be one only if both graphs have a one on that fragment).

```
(fr <= 1+px) * (fr >= 1-px) >> add;
```

Another way of thinking this is by using the mathematical function of a circumference. For any `x`

, we have to paint only the `y`

that follow the formula `x^2 + y^2 = 1`

. Isolating the `y`

we get:

```
f << [-1,1]*(sqrt $ 1-fx*fx);
mono $ point [fx, f] >> add;
```

Note how the square root is multiplied by `[-1,1]`

in order to take both roots.

Now we can take both ways of thinking and mix them. We’ll paint white only those fragments whose x-coordinate is near the computed y for the circle at that x:

```
c << sqrt (1-fy*fy);
between [c-px, c+px] $ abs fx >> add;
```

In the last example, we are only taking the positive root of the square root, but are taking the absolute value of x to make the graphic symmetrical.

Yet another way of thinking this problem: we already have a function that draws circles. Let’s tweak it to draw a circumference instead.

In this example, we draw a circle of radius 1, and then take off a slightly smaller circle:

```
(circle 0 2) - (circle 0 $ 2-2*px) >> add;
```

Next is mathematically equivalent to the last one, but we get here with another way of thinking. We can draw the inner part of the circumference with a circle, and also the outer part with an inverted slightly bigger circle (using `1-`

to invert the result, as it is all 0 and 1). So, we have obtained just the invert of what we what, so we invert the result again:

```
1-(1-circle 0 (2+2*px) + circle 0 (2-2*px)) >> add;
```

Finally, a last way to solve the problem is by transforming coordinates from Cartesian to polar. If you think about it, a circumference has a very easy representation on polar coordinates, as one of them (the radius) is constant.

This is exactly what vertical and horizontal lines are: a graph where one of the two coordinates is constant.

So we can draw a vertical line, and then think of it a circumference in polar coordinates, so when we interpret the x as the radius and the y as the angle, we get a circumference:

```
setfxy frt $ vline 1 px >> add;
```

Similarly, we can use a horizontal line, and the we need to interpret the x coordinate as the angle, and the y coordinate as the radius:

```
setfxy [ft,fr] $ hline 1 px >> add;
```

Bonus track: set feedback to 100% and use a point like it is a pencil:

```
spin (saw 0.06) $ point [0,1] >> add;
fb fxy >> add;
```

### Implementing Hydra functions

As explained in the Overview, Hydra is a popular language for live-coding visuals, and one of the differences between both languages is that Punctual is a bit lower-level than Hydra.

That implies that it’s relatively easy to implement Hydra functions using Punctual, but it’s not so easy the other way back.

Let’s develop a couple of examples.

- Implementing Hydra’s
`osc()`

function:

What `osc()`

does is drawing a sine wave, but as if we were looking from above. When the sine wave is far away (low), we see black, and as it gets nearer our point of view, it gets whiter.

Essentially, that is `abs fx`

(see Mathematical functions). We use `abs`

to get a symmetrical value that will render without jumps (the result, from left to right goes from 1 to 0 and then from 0 to 1 again, so it’s similar to a sine wave even though it’s not).

Then, we repeat this result with `tile`

(see Geometric transformations), and finally, animate the result using an Oscillator and `move`

:

```
move [(-1)*saw 0.1,0] $ tile [8,1] $ abs fx >> add;
```

Note that this is just an approximation, and the result is similar but not identical to the Hydra’s `osc()`

function.

- Implementing
`osc().kaleid()`

:

Now that we have something similar to the Hydra `osc()`

functions, we can extend it with some transformations, for example `kaleid`

.

`kaleid`

take the upper left part of an image, and repeat it several times, rotating a bit each repetition, to create a kaleidoscope effect. It also centers the result.

In this example, we are implementing `kaleid(5)`

.

- First line is our approximation to the Hydra’s oscillator.
- Second line: we divide the whole circumference into 5 parts.
- Third line: if you try to render this without any transformation (
`b << a;`

), you’ll notice that the result is a but rotated. Here we take the angle and correct this rotation, to make all parts fit together. - Forth line: we take the oscillator (
`c`

), and apply a coordinate transformation.

Note that the formula inside `setfxy`

is the one we would use to transform from polar coordinates to Cartesian using basic trigonometry, but we use to previously computed angle instead of the original `ft`

.

```
c << move [(-1)*saw 0.1,0] $ tile [8,1] $ abs fx;
a << ft % (2*pi/5);
b << a + (-1)*pi/5;
fit 1 $ setfxy [fr*cos b, fr*sin b] $ c >> add;
```

Of course, this is complicated to deduce, but as Hydra is free software, we can look up the original `kaleid`

implementation and translate the code to Punctual.

## Feedback

Was this page helpful?

Glad to hear it! Please tell us how we can improve.

Sorry to hear that. Please tell us how we can improve.