DEV Community

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

Posted on

3 1

"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.