# Hearty maths with calculang ❤️

calculang
mathsart
Author
Published

August 3, 2023

Few models I’ve worked on in my life have been lovelier than the ❤️ visual I made for my Twitter followers on Valentines day.

The missing interaction is finally below, along with some help about how it works. I did my best to choose somewhat self-explanatory input names 🙂

Code
``````embed(
calcuvizspec({
models: [beating],
input_cursors: [{pinchiness_in, radius_in, waviness_in, tallness_in, use_wave_override_in: false}],
mark: 'point',
encodings: {
x: {'name': 'x_in', type:'quantitative', domain: _.range(-6,6,0.05)},
y: {'name': 'heart', type: 'quantitative' },
color: {'name': 'x_in', type:'nominal', domain: _.range(-6,6,0.05), legend: false},
},
width: 300, height:250
}))``````

.

.

## How it works

The visual is a scatterplot of a `heart` formula against a range of different `x_in` input values from -6 to 6.

The calculang formula for `heart` is:

``heart = () =>  trend()   +   semi_circle() * wave() * tallness()``

There are 2 terms being added here:

• `semi_circle() * wave() * tallness()`: the components of this term are discussed below
• `trend()`: effectively a base or ‘spine’ of the heart shape

### visually 📊

Let’s first visualize `trend` or the base or ‘spine’:

Code
``````embed(
calcuvizspec({
models: [beating],
input_cursors: [{pinchiness_in, radius_in, waviness_in, tallness_in, use_wave_override_in: false}],
mark: 'line',
encodings: {
x: {'name': 'x_in', type:'quantitative', domain: _.range(-6,6,0.05)},
y: {'name': 'value', type: 'quantitative' },
row: {'name': 'formula', type:'nominal', domain: ['trend']},
color: {'name': 'formula', type:'nominal', domain: ['trend'], legend: false},
},
width: 300, height:50
}))``````

Now let’s look at the components of the term that is added to `trend`; recall that these are multipled together (they are factors):

Code
``````embed(
calcuvizspec({
models: [beating],
input_cursors: [{pinchiness_in, radius_in, waviness_in, tallness_in, use_wave_override_in: false}],
mark: 'line',
encodings: {
x: {'name': 'x_in', type:'quantitative', domain: _.range(-6,6,0.05)},
y: {'name': 'value', type: 'quantitative' },
row: {'name': 'formula', type:'nominal', domain: ['semi_circle','wave', 'tallness']},
color: {'name': 'formula', type:'nominal', domain: ['semi_circle','wave', 'tallness'], legend: false},
},
width: 300, height:50
}))``````

It’s value moves smoothly between -1 and 1 (inclusive); this adds noise that makes the points scatter across the shape of the heart.

To make it easier to visualise how this works, we can remove the noise.

In the following `wave` is no longer a sine wave: it’s a constant `-1` or `+1` representing the limits of the sine wave. I’m also showing 0 so we can see that the result is `=` `trend` in this case:

Code
``````embed(
calcuvizspec({
models: [beating],
input_cursors: [{pinchiness_in, radius_in, waviness_in, tallness_in, use_wave_override_in: true}],
mark: 'line',
encodings: {
x: {'name': 'x_in', type:'quantitative', domain: _.range(-6,6,0.05)},
y: {'name': 'value', type: 'quantitative' },
column: {'name': 'formula', type:'nominal', domain: ['heart','wave','trend'], legend:true},
color: {name: 'wave_override_in', type: 'nominal', domain: [-1,1,0]},
},
width: 150, height:150
}))``````
Code
``````embed(
calcuvizspec({
models: [beating],
input_cursors: [{pinchiness_in, radius_in, waviness_in, tallness_in, use_wave_override_in: false}],
mark: { type: 'line', stroke: 0.1, point: {size: 3, filled: false} },
encodings: {
x: {'name': 'x_in', type:'quantitative', domain: _.range(-6,6,0.05)},
y: {'name': 'value', type: 'quantitative' },
column: {'name': 'formula', type:'nominal', domain: ['heart','trend','wave'], legend: false},
},
width: 150, height:150
}))``````

The `heart` visual here is the same (mathematically) as the one at the top 😀

.

.

## credits

This blog was made with calculang, a language for calculations for transparency, education and certainty about numbers and maths, and maths art 🎨

Tip

You can find the calculang model source code by opening Developer Tools (Ctrl+Shift+I) and navigating to the `.cul.js` file (Ctrl+P and search `.cul.js`).

This example is inspired by heart functions I found written in Desmos - which has lots of awesome maths art 💚, I used this one as a reference.

For feedback you can contact me; or for issues/suggestions please use “Report an Issue” below ↓

|