From: Martin DeMello Date: 2008-09-10T14:44:31+09:00 Subject: Re: [QUIZ] Equation Graphing (#176) Here's my solution, using _why's wonderful little shoes toolkit. Run like shoes graph.rb "x*x; -5; 5; 0; 25" The args are "fn; xmin; xmax; ymin; ymax" I tried to make the code as straightforward as possible, to recapture the feel of the old Basic days. A few inevitable complications, due to shoes being a work in progress: the Grapher class is to work around scoping quirks, and the range check is due to a bug that doesn't let the exception handler catch an overflowing Bignum -> long conversion in the canvas code (it would've been nice to simply draw to a point off-canvas and let the drawing engine cope). Also shoes's argv handling code puts the filename in ARGV[0] and doesn't like negative numbers as plain command line args (they are treated as shoes args), so a single quoted string was the simplest thing that worked. #------------------------------------------------------------------------------------------------------ # ARGV[0] is the filename, since we launch via shoes graph.rb args ARGV.shift args = ARGV[0].split(";").map {|i| i.chomp} F = args.shift Xmin, Xmax, Ymin, Ymax = args.map {|i| i.to_f} X = Y = 800 XScale = X * 1.0/(Xmax - Xmin) YScale = Y * 1.0/(Ymax - Ymin) class Grapher def at(x,y) [((x -Xmin)* XScale).to_i, Y - ((y - Ymin) * YScale).to_i] rescue nil end def bounded?(x,y) x && y && 0 <= x && x <= X && 0 <= y && y <= Y end def fn(x) y = eval(F) end end Shoes.app :height => Y, :width => X do g = Grapher.new background rgb(255, 255, 255) fill white stroke black strokewidth 1 u, v = nil Xmin.step(Xmax, (Xmax - Xmin)/(X*1.0)) {|i| begin x0, y0 = g.at(u,v) u, v = i, g.fn(i) x, y = g.at(u,v) if g.bounded?(x,y) and g.bounded?(x0,y0) line(x0, y0, x, y) end rescue end } end