Learning Curves
When I was at RailsConf a week and a half ago, I had the pleasure of attending a Hackety Hack demonstration put on by Brian DeLacey, one of the original Hackety Hackers, maintainer of a blog about Hackety, and all-around good guy. There, I got to meet Evan Farrar, who I’d previously only talked to via the Scribble mailing list. We talked about various Scribble-related things, and eventually got to curves. We both agreed: curves in Scribble were just terrible. To refresh your memory, here’s a snippet of how you might scribble out a smiley face:
scribble(100, 10) do |s| s.line(100, 60) s.jump(150, 10) s.line(150, 60) s.jump(80, 70) s.curve(125, 90, [80, 80], [100, 90]) s.curve(170, 70, [150, 90], [170, 80]) end

This creates the pleasant visage you see to the right.
Now, that was all well and good,
except for those last two calls to curve.
What’s up with those?
Three parameters?
The first one is pretty obviously the end point,
just like line and jump,
but what are those last two?
Now, if you’re familiar with computer graphics,
you’ve probably heard of Bézier curves.
However, if you aren’t familiar with computer graphics,
like Scribble’s target audience,
chances are very high that you have no idea
what a Bézier curve is.
This is a problem,
because curve is literally defining a Bézier curve.
So, the obvious question now is
“What the heck is a Bézier curve?”
A Bézier curve, so named for their creator, Pierre Bézier,
is a sort of curve that can be defined in terms of four points:
the points where the curve begins and ends,
and two special control points.
One of the control points affects how curved the beginning of the curve will be,
and the other the end,
based on how far away they are from their respective endpoints.
These are the two additional points that need to be defined for curve.
Here’s a visual example,
taken from the Inkscape vector graphics program:

The solid black line is the actual curve. The empty circles are the control points, with blue lines pointing back to their respective endpoints. Hopefully, that helps you get something of an intuitive picture of how these curves work. I’ve found it’s very helpful to open a vector graphics program like Inkscape and just play around with the curves.
Of course, not everyone who uses Scribble’s going to do that. Thus, they’ll never have an intuitive picture of Bézier curves and will probably just give up with them altogether. And that would suck!
So a solution had to be found. There had to be some way to get users to be able to make curves without needing this sort of knowledge.
The trick that I used to resolve this was one that has a fine tradition within the Ruby community, and with Rails especially: sensible defaults. Rather than trying to come up with a better metaphor for having users make curves, why not just make the curves look nice automatically?
It took me a while to figure out just the right behavior that curves should default to. I tried having the control points default to pointing away from the end point of the previous curve in the scribble, but this didn’t end up looking nice at all. For example1:

Then I hit upon something much nicer. I wanted the curve to have a smooth look, like it belonged between points on either side. So why not have the position of the control points mirror the line between those two points? That would create nice, reasonable-looking default curves! And so it did:

So that’s now the default setup for calls to curve that don’t pass in any control points.
Let’s see that smiley face script again:
scribble(100, 10) do |s| s.line(100, 60) s.jump(150, 10) s.line(150, 60) s.jump(80, 70) s.curve(125, 90) s.curve(170, 70) end

Cleaner, easier to understand, and more consistent. Yay! And the output looks even better than it did with the manual control points.
Now, if one wants more control, it’s still an issue, and it will be dealt with eventually (and hopefully nicely). But for now, the basic behavior is nice, and that’s all that’s needed to not drive people screaming from the program at the sight of this crazy, crazy function.
In other Scribble news, Jonathan Leighton has joined the core team2, and with his help (read: he did all the work) we’ve moved to RSpec for testing and the GUI had been delightfully revamped.
1 Note that this example has three Bézier curves strung together. This is the typical manner of creating more complicated curves.
2 I use the term “team” here loosely, as it’s really more of a core pair: him and myself.
About Me
Feed
Overview of make_resourceful 0.1.0



Hi Nathan, nice post – big up the team! :) I’ve uploaded another screenshot with our latest efforts, if you want to link to that instead.
Okay, I’ll update it. It’s probably futile to keep the screenshot updated for long, though, because we keep making it better and better. Even that shot doesn’t have the new font I added in last night.
Nice! I have been putting it through the paces
size(500,500) points = [] 22.times{ points << (rand 500) } scribble(*x=[points.pop,points.pop]) do |s| 10.times{s.curve points.pop,points.pop} s.curve *x endLooks pretty neat to me :) I’ll have to check it out when I get home.