SDL2 で塗りつぶした楕円の回転
塗りつぶした楕円は、回転させなければ、円の塗りつぶしと同様に描くことができます。
void fill_oval(SDL_Renderer *renderer, int sx, int sy, int a, int b, int angle) { SDL_Point p1, p2; int x, y; for( x = -a; x <= a; x++ ) { y = sqrt(1.0 - (double)(x*x)/(a*a))*b +0.5; p1.x = x, p1.y = y; rotate(&p1, angle); p2.x = x, p2.y = -y; rotate(&p2, angle); SDL_RenderDrawLine(renderer, sx + p1.x, sy - p1.y, sx + p2.x, sy - p2.y); } }

ところが、回転させると、うまく塗りつぶせません。

別な考え方で塗りつぶします。楕円の方程式は以下です。

ある点が、この楕円の中にあるかどうかを判断し、楕円の中にあれば点を描画し、無ければ描画しない。という手順で塗りつぶしを行います。(x, y) が楕円内にあるかどうかは、次の式で判断できます。

上記の式をちょっと変形しておきます。

これを使い、楕円を塗りつぶしてみます。
void fill_oval(SDL_Renderer *renderer, int cx, int cy, int a, int b) { int x, y, result, out; out = a*a * b*b; for( x = -a; x <= a; x++ ) { for( y = -b; y <= b; y++ ) { result = (x * x)*(b * b) + (y * y)*(a * a); if( result <= out ) { SDL_RenderDrawPoint(renderer, cx + x, cy - y); } } } }

これを回転出来るようにします。考え方としては、楕円を含む矩形を回転させ、調べる領域を求め、各点を調べるときに、逆に回転させ、調べます。
void rotate(SDL_Point *pt, int angle) { int x, y; double r; x = pt->x, y = pt->y; r = M_PI * angle / 180.; pt->x = x * cos(r) - y * sin(r); pt->y = x * sin(r) + y * cos(r); } void min_max(SDL_Point *p, SDL_Point *min, SDL_Point *max, int angle) { rotate(p, angle); min->x = min->x > p->x ? p->x : min->x; min->y = min->y > p->y ? p->y : min->y; max->x = max->x < p->x ? p->x : max->x; max->y = max->y < p->y ? p->y : max->y; } void fill_oval(SDL_Renderer *renderer, int cx, int cy, int a, int b, int angle) { int x, y, result, out; SDL_Point p, min, max; /* 回転後の描画範囲を求める */ min.x = max.x = 0; min.y = max.y = 0; p.x = -a, p.y = -b; min_max(&p, &min, &max, angle); p.x = -a, p.y = b; min_max(&p, &min, &max, angle); p.x = a, p.y = b; min_max(&p, &min, &max, angle); p.x = a, p.y = -b; min_max(&p, &min, &max, angle); out = a*a * b*b; for( x = min.x; x <= max.x; x++ ) { for( y = min.y; y <= max.y; y++ ) { p.x = x, p.y = y; rotate(&p, -angle); result = (p.x * p.x)*(b * b) + (p.y * p.y)*(a * a); if( result <= out ) { SDL_RenderDrawPoint(renderer, cx + x, cy - y); } } } }

これで塗りつぶしがおかしくなることはなくなりました。塗りつぶしの時は、この方法を使ったほうがいいようです。
ディスカッション
コメント一覧
まだ、コメントがありません