## Creating string art cardioid curves in Processing

In this article, we will see how to create this curve in Processing:

This is called a *cardioid* curve because it is (vaguely) heart shaped

## How it works

To draw the curve, we first create a set of points, evenly spaced around the circumference of a circle. We number these points starting at zero. In the image here there are 8 points numbered 0 to 7.

Now for each point `n`

we draw a line connecting it to the point numbered `n*2`

. So point 1 connects to point 2, point 2 connects to point 4, point 3 connects to point 6.

Point 4 should connect to point 8, but there is no point 8. To fix this, we use modulo arithmetic. Instead of `n`

we use `n modulo 8`

- that is, the remainder when `n`

is divided by 8. When you divide 8 by 8, the remainder is 0, so point 4 connects to point 0.

Point 5 should connect to point 10. 10 modulo 8 is 2, so point 5 actually connects to point 2. And so on.

Unfortunately, we can’t see the full effect with just 8 points. The original image above uses 200 points around the circle, and shows the cardioid curve in all its glory!

## The code

We will follow similar scheme to the previous article on parabolic curves:

`circlePoints`

creates a circle of equally spaced (x, y) points.`joinPoints`

takes the circles of points and joins each point`n`

to the point`n*2`

.

### circlePoints

Here is the code:

```
PVector[] circlePoints(float cx, float cy, float r, int count)
{
PVector[] points = new PVector[count];
for (int i = 0; i < count; i++)
{
float x = cx + r*cos(TWO_PI*i/count);
float y = cy + r*sin(TWO_PI*i/count);
points[i] = new PVector(x, y);
}
return points;
}
```

This takes four parameters:

- the centre of the circle
`(cx, cy)`

- the radius
`r`

`count`

- the total number of points

Again we will use the Processing class `PVector`

to represent the points (or pins) in the image. A `PVector`

stores an `x`

and a `y`

value.

The code uses the standard coordinate equations for a circle to calculate points that are evenly distributed at equal angles around the circumference. Since the total angle in a circle is 2 PI radians, the angle if the ith point is given by `TWO_PI*i/count`

.

Finally we return the full array of points.

### joinPoints

Here is the code:

```
void joinPoints(PVector[] p, float mul)
{
int count = p.length;
for (int i = 0; i < count; i++)
{
int j = (int)((i*mul) % count);
line(p[i].x, p[i].y, p[j].x, p[j].y);
}
}
```

This function accepts a lists of points, `p`

and the multiplication factor `mul`

. The value of `mul`

determines the relationship between the two pints that are connected. In our case, since we are conencting point `n`

to point `n*2`

, we must set `mul`

to 2.

### Main draw function

Here is the main `draw`

function:

```
void draw()
{
clear();
background(255);
noFill();
strokeWeight(1);
stroke(255, 0, 0);
PVector[] p = circlePoints(300, 300, 250, 200);
joinPoints(p, 2);
}
```

The centre of the image is at (300, 300), and we chose a radius of 250. We set the number of points to 200, which works well for an image of this size.

We create `p`

, a list of points equally spaced around the circle..

Finally we use `joinPoints`

to join the points around the circle. In this case we use the rule that point `n`

connects to point `n*2`

.