# Equation Graphing (#176)

**URL:** <https://www.ruby-forum.com/t/equation-graphing-176/148457>\
**Category:** Ruby\
**Created:** [September 13, 2008, 12:36am UTC](https://www.ruby-forum.com/t/equation-graphing-176/148457 "2008-09-13T00:36:58Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [September 13, 2008, 12:36am UTC](https://www.ruby-forum.com/t/equation-graphing-176/148457/1 "2008-09-13T00:36:58Z")

</div>

I have to say, I think Martin provided a great quiz here… His  
description was old-school, and most of the solutions have that  
feeling. In return, I’m looked at the solutions from a similar  
viewport. While the solution from _Jesse Brown_ is simple and makes  
use of `gnuplot` – and would generally be a good way to solve the  
problem – it ain’t old-school. (Of course, this means that if you  
have a real graphing problem, using `gnuplot` _would_ be a good idea.)

_Michael Suchanek_ provided a solution using RubyX11. Oh man, does  
that bring back memories… Michael just opened up a can of X11  
goodness that, with Ruby, looks trivial compared to my old X11 C code.  
I am rather tempted to study this library and start playing, but I do  
have papers to write and books to analyze. Please take a look at  
Michael’s code, because X11 is definitely old-school, definitely  
powerful, and RubyX11 makes it definitely cool.

The ASCII solution from _brabuhr_ is also several flavors of awesome.  
Heck, if we geeks can still be entertained playing ASCII games like  
[Nethack](http://www.nethack.org/) and [Dwarf Fortress](http://bay12games.com/dwarves/), then why not our function  
plotters? This solution is also totally Ruby, with a single, trivial  
function that accepts your “equation” as a block… Top notch, dear  
sir.

I am going to go into a bit of detail with _Martin DeMello_’s  
solution, not because he wrote the quiz, but it reminded me most of my  
_oldest_ coding experience: BASIC. Sure, there’s a class and a  
function or two in there, but I could imagine line numbers in front of  
the code and almost expected to see a `GOTO` statement in there  
somewhere.

Plus, it makes use of the cool, little, cross-platform Ruby library  
for making little applications: [Shoes](http://shoooes.net/). While Shoes still seems a  
little rough around the edges, it’s a fun environment and API, a kind  
of toy that recalls days on the Commodore 64. (I use Apple computers  
nowadays, but back then, Commondore was king!)

Here’s the main body:

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

```

There are three essential things going on here. First, the creation of  
a Shoes application and the calls to prepare it, such as `fill white`  
and `strokewidth 1`. Second is the creation of a `Grapher` object and  
the calls into it: we’ll come back to that. Finally, the main loop is  
here, contained in this one line:

```
        Xmin.step(Xmax, (Xmax - Xmin)/(X*1.0)) {|i|

```

`Numeric#step` is a method that works for either integers or floats,  
and counts from the first number (`Xmin`) up to the second number  
(`Xmax`) by the provided increment. Martin divides the window width  
into the user-specified domain. This increment will ensure the  
evaluations contained within the loop are evaluated once per  
horizontal pixel.

The multiplication by 1.0 serves to convert X (and the rest of that  
expression) to floating-point. Now, typically this might be done with  
the `to_f` method. But multiplying by 1.0 seems old-school, especially  
as it is one character less that `.to_f`. Rad.

The `Grapher` is a simple class containing three methods. `bounded?`  
and `fn` are fairly straightforward; the former checks that a  
coordinate pair is contained within the window’s drawing area, while  
the latter evaluates the function provided by the user. Then there’s  
`Grapher#at`:

```
def at(x,y)
    [((x - Xmin) * XScale).to_i, Y - ((y - Ymin) * YScale).to_i] 

```

rescue nil  
end

This function converts the pair `(x, y)` from function-space values to  
window-space values. That is, it maps the evaluation of the function  
to the appropriate coordinate within the Shoes window. There is some  
repetition here that could stand to be refactored into a general  
`lerp` method (i.e. linear interpolation), but as we’re in old-school  
mode, I’ll let it slide.

So, back in the main loop, we can now read this easily. For each  
iteration, we evaluate the provided function at each pixel column of  
the domain (`i`, stored to `u`) to get the pixel row (`v`) via method  
`fn`. The `(u, v)` pair is converted to window coordinates `(x, y)`  
via method `at`. The previous window coordinate is recalculated into  
`(x0, y0)`, and the Shoes’ `line` method is called to draw a line  
between the two window coordinates.

Good show, gents. Now, if I can get Ruby running on this ol’ Commodore  
64 sitting in the closet, my life will be complete.

New quiz will show up later this evening, or early tomorrow morning.  
Quick hint: it’s about time to finish the final part of the  
Statistician quiz.

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [September 13, 2008, 2:12am UTC](https://www.ruby-forum.com/t/equation-graphing-176/148457/2 "2008-09-13T02:12:56Z")

</div>

On Fri, Sep 12, 2008 at 2:54 PM, Matthew M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> The ASCII solution from _brabuhr_ is also several flavors of awesome.  
> Heck, if we geeks can still be entertained playing ASCII games like  
> [Nethack][1] and [Dwarf Fortress][2], then why not our function  
> plotters? This solution is also totally Ruby, with a single, trivial  
> function that accepts your “equation” as a block… Top notch, dear  
> sir.

Another very neat feature is it can handle equations of the general  
form f(x,y) = 0, rather than the more limited y = f(x)

martin
