[vox-tech] [OT] Math question: help me make a rainbow
Bill Broadley
bill at cse.ucdavis.edu
Tue Mar 31 19:21:36 PDT 2009
Bill Kendrick wrote:
> Tux Paint has a magic tool called "Rainbow." It's not really, it's just
> a color-cycling circle-shaped paintbrush. A few years ago, a couple of
> the other TP developers joked that we need a tool to draw real rainbows.
> (Draw an arc, and the rainbow gradient appears over it.)
>
> So I've decided it might be fun to take a stab at it. My main problem is
> I'm rusty with math (trig., geometry, etc. ... you don't use those much in PHP
> or MySQL. ;) Heck, you don't use them much in most of the kinds of games I've
> worked on over the years.)
>
> Here's how I imagine the UI working. Click mouse to select one endpoint
> of the rainbow. Drag to where you want the other endpoint, and release
> mouse. Rainbow gets drawn.
>
> The rainbow would be an upside-down-"U" shape (with a 1:1 aspect, e.g.
> it'd be a portion of a perfect circle). I think for artistic purposes,
> it shouldn't always be a complete 180-degree arc, though. So here's
> how I complicate the UI :)
>
> P1 (aka x1,y1) is where you click. P2 (aka x2,y2) is where you release.
>
> 0,0 is the top left of the screen. Angles go from 0 (bottom/right of arc)
> thru 90 (top/center of arc) to 180 (bottom/left of arc).
>
> If y1 >= y2, then P1 represents the 180th degree of the arc
> (going counter-clockwise from the far right of the circle), and
> P2 represents the Nth degree of the arc (where 0 <= N < 180)
>
> If y1 < y2, then P1 represents the Nth degree of the arc,
> and P2 represents the 0th degree.
>
> This will let you draw, e.g. (bad ASCII ahead):
>
> /==P2
> /
> |
> P1
>
> as well as the full semi-circular arc:
>
> /==\
> / \
> | |
> P1 P2
>
> and of course, if P2 is lower, then:
>
>
> /==\
> P1 \
> |
> P2
>
> In both cases, there's an invisible P3, which is at 0 degrees or 180 deg.,
> depending on which point ended up being lower. The center of the circle
> is not necessarily exactly at (x1+((x2-x1)/2) , max(y1,y2)) which is where
> I'm getting stuck.
>
> My initial though was to find the vector V between P1 and P2.
> Going off at the normal of V, from its center, I believe I get a line
> that strikes the center of my would-be circle, when it crosses the
> max(y1,y2) height down the screen.
>
> But I was up late thinking about this, and worrying about atan() and
> intersect tests, and starting to think there's a simpler way.
>
>
> So, given two points on an arc of a circle, P1 and P2, how do I find
> the center and radius of the circle? (Then all I need to do is determine
> the angle (N) of one of the points (P1 or P2), while I know that the
> angle of the other (P2 or P1) is 0 or 180, depending on my UI rules above.
>
> Whew. Did I make ANY sense? :)
Some. Not sure what you are getting at though. You want to draw 180 degrees
of a circle with the end points defined by p1 and p2? What if you want to
make an upside down rainbow? Or 1/2 of one?
In any case the center is trivial. Lets call the center M, so:
M.x = abs ( p1.x - p2.x ) / 2 + p1.x
M.y = abs ( p1.y - p2.y ) / 2 + p1.y
Oh, and radius:
r = dist ( p1 - p2 ) /2 # sqrt ( x^2 - y ^2)
Now you just need the starting angle and ending angle.
Diff_in_y = m.y - p1.y
Diff_in_x = m.y - p1.x
start_angle = tan (diff_in_y/diff_in_x)
Repeat for P2.
Then something like:
for i in start_angle to stop_angle: # this assumes degrees, but similar in
# radians
delta_x = radius * cos(i)
delta_y = radius * sin(i)
draw_pixel(M.x + delta_x, m.y+delta_y)
Then something like:
for color in 0 to 64:
drawHalfCircle(p1,p2,color)
Then inside drawHalfCircle the above with a:
r=r+color.
>
>
More information about the vox-tech
mailing list