Valentine's Day Equation Plotted in Ruby

Teaching kids programming through math art and heart-shaped graphs

valentines-heart-graph.png

TLDR: Use Ruby and GNUPlot to plot the mathematical Valentine’s Day heart equation. Perfect for teaching kids programming through something they relate to.


I’m trying to expose my kids to programming bit by bit. 😊 Things that work the best are something that they relate to. Almost right on cue, this blog post came up on my feed on dev.to on Saturday and I thought it would be a fun activity to help kids make Valentines in a new way. Thank you, @DevLorenz0 for the formula! ❤️

All you need is Ruby & GNUPlot, and possibly GNUPlot official docs PDF if you want to experiment further.


Installation

# on Mac
brew install gnuplot
gem install gnuplot

# Chocolatey has a package for Windows
# choco install gnuplot

# Use rpm / apt on Linux
# apt-get install gnuplot

The Code

# valentine_day_plot.rb
# Tested on Ruby 2.7.2
require 'rubygems'
require 'gnuplot'

valentines_day_function = lambda { |t|
  x = 16 * Math.sin(t)**3
  y = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t)
  # Experimentally found that rounding to 4
  # produces the best results for us
  [x.round(4).to_f, y.round(4).to_f]
}

# Adjust this to get more or less number of plot points
# At the end we transpose array, to shape data for
# Gnuplot::DataSet input below
DISTANCE_BETWEEN_POINTS = 0.0001
COORDINATES = (0..(2 * Math::PI)).step(DISTANCE_BETWEEN_POINTS)
                                 .to_a
                                 .map do |t|
  valentines_day_function.call(t)
end.transpose

Gnuplot.open do |gp|
  Gnuplot::Plot.new(gp) do |plot|
    plot.output 'valentine_day_plot.pdf'
    # Sized as a nice square to be printed on a A4 or US Letter page
    plot.terminal 'pdf colour size 8in,8in'

    # The following is self-explanatory, but setting range too small,
    # will put the graph out of bounds
    plot.xrange '[-20:20]'
    plot.yrange '[-20:20]'
    plot.title  "Valentine's Day Equation"
    plot.ylabel 'Love-y'
    plot.xlabel 'Love-x'

    # DataSet.new can also take the formula directly, not just an array
    # of shape [x-coordinates, y-coordinates]
    plot.data << Gnuplot::DataSet.new(COORDINATES) do |ds|
      # You can also draw graph using various other types,
      # 'linespoints','steps','fillsteps', etc
      # See http://www.gnuplot.info/docs_5.4/Gnuplot_5_4.pdf
      # for full docs
      ds.with = 'lines'
      ds.linewidth = 15
      # Change this to the name of your Valentine
      ds.title = 'My Valentine'
    end
  end
end

The Result

Valentine's Day heart graph plotted with smooth lines using Ruby and GNUPlot

Here is an example of the plotted graph if we change DISTANCE_BETWEEN_POINTS = 0.1 and ds.with = 'steps' and ds.linewidth = 1:

Valentine's Day heart graph plotted with steps style showing discrete points


Bonus: Converting to Image Formats

The PDF we generated above is perfect for printing, but if you wanted to convert it to a JPEG or PNG, you can use a graphics app like Photoshop or GIMP, or simply use ImageMagick:

# Install it if you don't have it
brew install imagemagick
convert -quality 300 -density 300 valentine_day_plot.pdf valentine_day_plot.jpg

Resources


Originally published: dev.to/konung/valentine-s-day-equation-plotted-in-ruby-6lo


Last updated: February 15, 2021

ruby gnuplot graphs math data visualization kids coding