回転付きの楕円塗りつぶし

回転付きの楕円塗りつぶし
前回までで回転について説明したので、ここで一旦円の塗りつぶしに戻って、今度は回転付きの楕円塗りつぶしを描画してみたいと思います。
スクリーンショット


左クリックで、15 度単位で回転します。
ソースコード
024_rotate3.c
#include <math.h>
#include "sptk.h"

#define PI 3.141592
#define SUBPIXEL  5

SPTK_IMAGE *img;
int angle = 0;

void draw_fill_ellipse_rotation(double yscale)
{
    int ix,iy,jx,jy,cnt,val;
    double xx,yy,dx,dy,r,dcos,dsin,rd;
    
    r = 85;
    
    rd = angle * PI / 180.0;
    dcos = cos(rd);
    dsin = sin(rd);
    
    for(iy = 0; iy < 200; iy++)
    {
        for(ix = 0; ix < 200; ix++)
        {
            /* オーバーサンプリング */
            
            cnt = 0;
        
            for(jy = 0; jy < SUBPIXEL; jy++)
            {
                for(jx = 0; jx < SUBPIXEL; jx++)
                {
                    xx = ix - 100 + jx * (1.0 / SUBPIXEL);
                    yy = iy - 100 + jy * (1.0 / SUBPIXEL);
                    
                    dx = xx * dcos - yy * dsin;
                    dy = (xx * dsin + yy * dcos) / yscale;
                    
                    if(dx * dx + dy * dy < r * r)
                        cnt++;
                }
            }
        
            val = 255 * cnt / (SUBPIXEL * SUBPIXEL);
            val = 255 - val;
        
            sptk_image_setpixel(img, ix, iy, SPTK_RGB(val, val, val));
        }
    }
}

void winhandle(SPTK_EVENT *ev)
{
    switch(ev->type)
    {
        case SPTK_EVENT_BTTDOWN:
            angle = (angle + 15) % 360;
            
            draw_fill_ellipse_rotation(0.4);
            sptk_update(NULL, 0, 0, 200, 200, 0);
            break;
        case SPTK_EVENT_WINDOW_CLOSE:
            sptk_quit();
            break;
    }
}

int main()
{
    sptk_init("test", 200, 200);
    sptk_window_set_handle(winhandle);

    img = sptk_window_get_image();
    
    draw_fill_ellipse_rotation(0.4);
    
    sptk_run();

    return 0;
}
解説
正円の状態を元にして考えると、円の縦方向を yscale 倍した後、回転を行うのですから、描画としてはその逆をやればいいことになります。

描画先の座標を、原点を (0, 0) とした位置で逆回転を行って、その後 Y 位置を yscale で割ると、正円における位置を求めることができます。