# Creative Coding Blog

Maths, coding and art

## 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.