[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