DEV Community

Cover image for Valentine's Day Equation Plotted in Ruby
kinvoki
kinvoki

Posted on • Originally published at kinvoki.com

Valentine's Day Equation Plotted in Ruby

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Resources


Last updated: February 15, 2021

Top comments (0)