CC: | bug-Imager [...] rt.cpan.org |
Subject: | aa filled circle drawing stupidly inefficient |
Date: | Fri, 23 Jan 2015 08:58:23 +1100 |
To: | Denis Howe <denis.howe [...] gmail.com> |
From: | tonyc [...] cpan.org |
Sorry, I missed this message in this old thread.
On Sun, Jan 11, 2015 at 04:22:12PM +0000, Denis Howe wrote:
Show quoted text
> Hi Tony,
>
> I used to fill circles by doing lots of calls to Imager::setpixel().
> Surely it would be quicker to call Imager::circle I thought, but it's
> considerably slower. For an anti-aliased circle, arc() calls i_circle_aa().
> Looking in draw.c, I found function make_minmax_list() which calculates
> the left and right ends of a row of pixels in the filled circle. I was
> surprised to find it iterating round a circle:
>
> for(angle = 0.0; angle<361; angle +=astep)
>
> That 361 should be 361*PI/180 = 6.3 since polar_to_plane() passes angle to
> sin() and cos(), which take radians.
>
> This means it's doing about 60 times more trig function calls than
> necessary, which might explain why it's a bit slow.
You're right.
Show quoted text> Similarly, in:
>
> astep = radius>0.1 ? .5/radius : 10;
>
> The angle subtended by 0.5 pixels at radius pixels is 0.5/radius in
> radians, which makes sense, but 10 radians is clearly nonsense and
> was obviously supposed to be 1/36 of a revolution, which is PI/18 radians.
> (Though I'm not sure if anyone cares how you plot circles of radius < 0.1
> pixels (or is it subpixels?)).
>
> All that aside, the whole algorithm puzzles me. Why iterate around a
> circle? Surely all you need to do is use Pythagoras on each row?
>
> dx = sqrt(radius*radius - dy*dy);
> xmin = xc - dx; xmax = xc + dc;
>
> or am I missing something?
I think you're right here too.
I'll look into fixing this for the next release.
Tony