How to create and visualize a cardioid using javascript
Tags: javascript, algorithms, canvas
Published: 2023-02-24 11:19:51

Hello everyone! Today we're going to create and visualize a cardioid using javaScript and canvas. Let's get started!

## Preparation

A cardioid is a geometric shape that resembles a heart. It is formed by tracing the path of a point on a circle that is rolling around another circle of the same size. The resulting curve has a single cusp at the origin, which gives it its characteristic heart shape. Cardioids are fascinating mathematical shapes that can be used in many different applications, from engineering to art.

In this article, we will explore how to create a cardioid using javascript and the canvas. We will use the canvas to draw the curve of the cardioid and javascript to calculate the coordinates of each point along the curve. We will also discuss the underlying mathematics behind the cardioid and provide a step-by-step guide for creating one. By the end of this article, you will have a deeper understanding of cardioids and how to create them using javascript and canvas.

## Theory

We start with a circle of radius `r` centered at the origin, and a fixed point `P` on the circle. We will draw a pencil of lines through `P` and rotate it around the circle.

To draw each line, we calculate the angle between the x-axis and the line using the formula `theta = (2π/N) * i`, where `i` is the index of the line.

For any angle theta, the line passing through `P` and intersecting the circle at angle `theta` is given by the equation:

`xcos(theta) + ysin(theta) = rcos(theta)`

To find the intersection points of the line and the circle, we substitute the equation of the line into the equation of the circle and solve for `x` and `y`. This gives us a system of equations:

`xcos(theta) + ysin(theta) = rcos(theta)`
`x^2 + y^2 = r^2`

By solving this system of equations for `x` and `y`, we get:

`x = rcos(theta) + rcos(2theta)`
`y = rsin(theta) + rsin(2theta)`


![Cardioid as envelope of a pencil of lines](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l0t744pmewr2r503v67a.png)

These equations give us the coordinates of the point of intersection of the line passing through `P` and intersecting the circle at a given angle `theta`.

To draw the cardioid, we simply plot the points of intersection as we vary the angle theta `from 0 to 2π`, and connect them with a smooth curve.



## Environment setup

Let's define the Cardioid class that will store the state of the cardioid and have two main methods: drawing the cardioid on the screen and getting color of the line:

```javascript 
class Cardioid {
  constructor() {}

  get color() {}

  draw() {}
}
```

Next, we're going to define a new class called `Canvas` that will create the canvas element and call the draw method of the Cardioid class:

```javascript
class Canvas {
  constructor(id) {
    this.canvas = document.createElement("canvas");

    this.canvas.id = id;
    this.canvas.width = window.innerWidth;
    this.canvas.height = window.innerHeight;

    document.body.appendChild(this.canvas);
    this.ctx = this.canvas.getContext("2d");
  }

  draw() {
    const cardioid = new Cardioid(this.ctx);
    const draw = () => {
      this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
      cardioid.draw();
      requestAnimationFrame(draw);
    };
    draw();
  }
}
```

Consequently, the preparatory phase of the project has been finalized and we can now proceed to the implementation of its principal functionalities.

## Cardioid

To generate the most basic form of the cardioid, the initial parameters of the class are defined as the radius of the circle, the quantity of lines and the coordinates of the screen center to set the offset of the points:

```javascript
class Cardioid {
  constructor(ctx) {
    this.ctx = ctx;
    this.radius = 400;
    this.num_lines = 200;
    this.translate = [window.innerWidth / 2, window.innerHeight / 2];
  }

  get color() {}

  draw() {}
}
```
The Cardioid class includes a draw method that is responsible for rendering the cardioid on a canvas element. The method does not take any arguments, as the required parameters are specified in the constructor.

To draw the cardioid, the draw method loops over the number of lines defined in the constructor, calculating the two points of intersection for each line using the theory above. Nevertheless, in order to connect two pairs of points with a line, it is necessary to decompose the original equations for x and y into a set of two equations of the following form:

`x1 = rcos(theta) + offsetX`
`y1 = rsin(theta) + offsetY`

`x2 = rcos(2theta) + offsetX`
`y2 = rsin(2theta) + offsetY`

Thus, the following implementation is obtained:

```javascript
class Cardioid {
  constructor(ctx) {
    this.ctx = ctx;
    this.radius = 400;
    this.num_lines = 200;
    this.translate = [window.innerWidth / 2, window.innerHeight / 2];
  }

  get color() {}

  draw() {
    this.ctx.lineWidth = 1;

    for (let i = 0; i < this.num_lines; i++) {
      const theta = ((2 * Math.PI) / this.num_lines) * i;
      const x1 = this.radius * Math.cos(theta) + this.translate[0];
      const y1 = this.radius * Math.sin(theta) + this.translate[1];

      const x2 = this.radius * Math.cos(2 * theta) + this.translate[0];
      const y2 = this.radius * Math.sin(2 * theta) + this.translate[1];

      this.ctx.strokeStyle = this.color;
      this.ctx.beginPath();
      this.ctx.moveTo(x1, y1);
      this.ctx.lineTo(x2, y2);
      this.ctx.stroke();
    }
  }
}
```

Let's see how the cardioid looks in real time:

{% codepen https://codepen.io/anstertum/pen/rNZLXmq %}

Since the cardioid resembles a heart, we can incorporate a beating effect. This can be accomplished by selecting a sin function to modulate the radius of the cardioid as follows:

`y = abs(sin(x) - 0.5)`

As a result, we get the following picture:

{% codepen https://codepen.io/anstertum/pen/yLxJmKq %}

Next, let's depart from the standard procedure for constructing a cardioid and introduce a variable `factor `that depends on time. Additionally, instead of simply doubling the value of the angle theta, we will use this variable to compute the second pair of points:

`factor = 1 + 0.0001 * time`

Next, let's modify the approach of calculating the time value. To achieve this, we can define the `startTime` value as `performance.now()` within the constructor of the `Cardioid` class and subsequently implement the time getter as the difference between `performance.now()` and `startTime`:

```javascript
get time() {
  return performance.now() - this.startTime;
}
```

The resulting outcome is presented below:

{% codepen https://codepen.io/anstertum/pen/wvEWVYr %}

## Conclusion

In conclusion, we have explored the theory of the cardioid as the envelope of a pencil of lines and demonstrated how this concept can be used to create cardioids in javascript using the canvas element. Furthermore, we have showcased various techniques that can be used to add visual effects to the cardioid, such as a beating effect. By leveraging the power of javascript and the canvas element, the possibilities for creating engaging and interactive cardioids are endless and you can try to create your own implementation right now!