DEV Community

Cover image for "Valentine's Day Equation" plotted in Ruby
konung
konung

Posted on

"Valentine's Day Equation" plotted in Ruby

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.

# on Mac
brew install gnuplot
gem install gnuplot 

# Chocolotey has a package for Windows
# choco install gnuplot 

# Use rpm / apt on Linux
# apt-get install gnuplot
Enter fullscreen mode Exit fullscreen mode

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 variaous 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

Result

Valentine Day Graph plotted with lines

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 Day Graph plotted with steps

Bonus

PDF we generated above is perfect for printing, but if you wanted to convert it to an 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

Top comments (2)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.