プログラムリスト
#include <stdio.h>
#include <math.h>
#include <eggx.h> /* EGGX を使う時に必要 */
/*************************
* 角度を0〜2πの間に変換する
* 引数 double angle: 角度
* 戻り値 0〜2πの間の角度
*/
double Rangle(double angle)
{
while(angle<0) angle += 2*M_PI;
while(angle>=2*M_PI) angle -= 2*M_PI;
return angle;
}
/***************************
* 楕円と中心から角度angleで伸びる直線との交点を求める
* 引数 int x: 中心のx座標
* int y: 中心のy座標
* int rx: x方向半径
* int ry: y方向半径
* int angle: 角度(0〜2π)
* int px: 交点x座標
* int py: 交点y座標
* 戻り値 なし
*/
void calcArcPoint(int x,int y,int rx,int ry,double angled,int *px,int *py)
{
double r,a,b;
angled = Rangle(angled);
r=1.0;
a=1.0/((double)rx*(double)rx);
b=1.0/((double)ry*(double)ry);
if(angled==M_PI/2) { //90度
*px = x;
*py = y - ry;
} else if(angled==M_PI*3/2) { //270度
*px = x;
*py = y + ry;
} else {
double m = tan(angled);
*px = sqrt((r*r)/(a + b * m*m));
*py = sqrt((r*m*r*m)/(a + b * m*m));
if(angled<M_PI/2) {
*px = x + *px;
*py = y - *py;
} else if(angled<M_PI) {
*px = x - *px;
*py = y - *py;
} else if(angled<M_PI*3/2) {
*px = x - *px;
*py = y + *py;
} else {
*px = x + *px;
*py = y + *py;
}
}
}
/*************************
* フレームバッファに楕円を描く
* 引数 int cx,cy: 円の中心座標
* int rx: x方向の半径
* int ry: y方向の半径
* double Sangle: 描画スタート角度
* double Eangle: 描画終了角度
* 戻り値 なし
*/
void grArc(int win,int cx, int cy, int rx,int ry, double Sangle,double Eangle)
{
int dx, dy, s ;
int x1, y1, x2, y2, x3, y3, x4, y4 ;
int sx,sy,ex,ey;
int psx, psy, pex, pey, ss, es, i, j ;
unsigned int pass[4] ;
calcArcPoint(cx,cy,rx,ry,Sangle,&sx,&sy);
calcArcPoint(cx,cy,rx,ry,Eangle,&ex,&ey);
psx = sx - cx ;
pex = ex - cx ;
psy = sy - cy ;
pey = ey - cy ;
// 始点の象限
if (psx >= 0) {
if (psy >= 0) ss = 3 ;
else ss = 0 ;
} else {
if (psy >= 0) ss = 2 ;
else ss = 1 ;
}
// 終点の象限
if (pex >= 0) {
if (pey >= 0) es = 3 ;
else es = 0 ;
} else {
if (pey >= 0) es = 2 ;
else es = 1 ;
}
if (ss == es) { // 始点終点の象限が同じ
if (((psy < 0) && (psx >= pex)) ||
((psy >= 0) && (psx <= pex))) {
for (i = 0 ; i < 4 ; i++) pass[i] = 0 ; // 小円( < 90 )
pass[ss] = 5 ;
} else {
for (i = 0 ; i < 4 ; i++) pass[i] = 1 ; // 大円( > 270 )
pass[ss] = 4 ;
}
} else {
for (i = 0 ; i < 4 ; i++) pass[i] = 0 ;
j = ss ;
for (i = 0 ; i < 4 ; i++) {
pass[j] = 1 ; // 全表示
if (j == es) break ;
++j ;
if (j > 3) j = 0 ;
}
pass[ss] = 2 ; // 始点のみ
pass[es] = 3 ; // 終点のみ
}
if(rx>ry) {
dx = rx ;
s = rx ;
dy = 0 ;
while (dx >= dy) {
unsigned int flag ;
int dxx = dx*ry/rx;
int dyy = dy*ry/rx;
x1 = cx + dx;
x2 = cx - dx;
x3 = cx + dy;
x4 = cx - dy;
y1 = cy + dyy;
y2 = cy - dyy;
y3 = cy + dxx;
y4 = cy - dxx;
flag = 0x00 ;
// 第1象限
switch (pass[0]) {
default:
break ;
case 1:
flag = 0x03 ;
break ;
case 2:
if ((x1 <= sx) && (y2 <= sy)) flag |= 0x01 ;
if ((x3 <= sx) && (y4 <= sy)) flag |= 0x02 ;
break ;
case 3:
if ((x1 >= ex) && (y2 >= ey)) flag |= 0x01 ;
if ((x3 >= ex) && (y4 >= ey)) flag |= 0x02 ;
break ;
case 4:
if (((x1 <= sx) || (x1 >= ex)) && ((y2 <= sy) || (y2 >= ey))) flag |= 0x01 ;
if (((x3 <= sx) || (x3 >= ex)) && ((y4 <= sy) || (y4 >= ey))) flag |= 0x02 ;
break ;
case 5:
if ((x1 <= sx) && (x1 >= ex) && (y2 <= sy) && (y2 >= ey)) flag |= 0x01 ;
if ((x3 <= sx) && (x3 >= ex) && (y4 <= sy) && (y4 >= ey)) flag |= 0x02 ;
break ;
}
// 第2象限
switch (pass[1]) {
default:
break ;
case 1:
flag |= 0x0C ;
break ;
case 2:
if ((x4 <= sx) && (y4 >= sy)) flag |= 0x04 ;
if ((x2 <= sx) && (y2 >= sy)) flag |= 0x08 ;
break ;
case 3:
if ((x4 >= ex) && (y4 <= ey)) flag |= 0x04 ;
if ((x2 >= ex) && (y2 <= ey)) flag |= 0x08 ;
break ;
case 4:
if (((x4 <= sx) || (x4 >= ex)) && ((y4 >= sy) || (y4 <= ey))) flag |= 0x04 ;
if (((x2 <= sx) || (x2 >= ex)) && ((y2 >= sy) || (y2 <= ey))) flag |= 0x08 ;
break ;
case 5:
if ((x4 <= sx) && (x4 >= ex) && (y4 >= sy) && (y4 <= ey)) flag |= 0x04 ;
if ((x2 <= sx) && (x2 >= ex) && (y2 >= sy) && (y2 <= ey)) flag |= 0x08 ;
break ;
}
// 第3象限
switch (pass[2]) {
default:
break ;
case 1:
flag |= 0x30 ;
break ;
case 2:
if ((x2 >= sx) && (y1 >= sy)) flag |= 0x10 ;
if ((x4 >= sx) && (y3 >= sy)) flag |= 0x20 ;
break ;
case 3:
if ((x2 <= ex) && (y1 <= ey)) flag |= 0x10 ;
if ((x4 <= ex) && (y3 <= ey)) flag |= 0x20 ;
break ;
case 4:
if (((x2 >= sx) || (x2 <= ex)) && ((y1 >= sy) || (y1 <= ey))) flag |= 0x10 ;
if (((x4 >= sx) || (x4 <= ex)) && ((y3 >= sy) || (y3 <= ey))) flag |= 0x20 ;
break ;
case 5:
if ((x2 >= sx) && (x2 <= ex) && (y1 >= sy) && (y1 <= ey)) flag |= 0x10 ;
if ((x4 >= sx) && (x4 <= ex) && (y3 >= sy) && (y3 <= ey)) flag |= 0x20 ;
break ;
}
// 第4象限
switch (pass[3]) {
default:
break ;
case 1:
flag |= 0xC0 ;
break ;
case 2:
if ((x3 >= sx) && (y3 <= sy)) flag |= 0x40 ;
if ((x1 >= sx) && (y1 <= sy)) flag |= 0x80 ;
break ;
case 3:
if ((x3 <= ex) && (y3 >= ey)) flag |= 0x40 ;
if ((x1 <= ex) && (y1 >= ey)) flag |= 0x80 ;
break ;
case 4:
if (((x3 >= sx) || (x3 <= ex)) && ((y3 <= sy) || (y3 >= ey))) flag |= 0x40 ;
if (((x1 >= sx) || (x1 <= ex)) && ((y1 <= sy) || (y1 >= ey))) flag |= 0x80 ;
break ;
case 5:
if ((x3 >= sx) && (x3 <= ex) && (y3 <= sy) && (y3 >= ey)) flag |= 0x40 ;
if ((x1 >= sx) && (x1 <= ex) && (y1 <= sy) && (y1 >= ey)) flag |= 0x80 ;
break ;
}
if (flag & 0x01) pset(win,x1,y2) ;
if (flag & 0x02) pset(win,x3,y4) ;
if (flag & 0x04) pset(win,x4,y4) ;
if (flag & 0x08) pset(win,x2,y2) ;
if (flag & 0x10) pset(win,x2,y1) ;
if (flag & 0x20) pset(win,x4,y3) ;
if (flag & 0x40) pset(win,x3,y3) ;
if (flag & 0x80) pset(win,x1,y1) ;
s -= 2 * dy + 1 ;
if (s < 0) {
--dx ;
s += 2 * dx ;
}
++dy ;
}
} else {
dx = 0 ;
s = ry ;
dy = ry ;
while (dy >= dx) {
unsigned int flag ;
int dxx = dx*rx/ry;
int dyy = dy*rx/ry;
x1 = cx + dxx;
x2 = cx - dxx;
x3 = cx + dyy;
x4 = cx - dyy;
y1 = cy + dy;
y2 = cy - dy;
y3 = cy + dx;
y4 = cy - dx;
flag = 0x00 ;
// 第1象限
switch (pass[0]) {
default:
break ;
case 1:
flag = 0x03 ;
break ;
case 2:
if ((x1 <= sx) && (y2 <= sy)) flag |= 0x01 ;
if ((x3 <= sx) && (y4 <= sy)) flag |= 0x02 ;
break ;
case 3:
if ((x1 >= ex) && (y2 >= ey)) flag |= 0x01 ;
if ((x3 >= ex) && (y4 >= ey)) flag |= 0x02 ;
break ;
case 4:
if (((x1 <= sx) || (x1 >= ex)) && ((y2 <= sy) || (y2 >= ey))) flag |= 0x01 ;
if (((x3 <= sx) || (x3 >= ex)) && ((y4 <= sy) || (y4 >= ey))) flag |= 0x02 ;
break ;
case 5:
if ((x1 <= sx) && (x1 >= ex) && (y2 <= sy) && (y2 >= ey)) flag |= 0x01 ;
if ((x3 <= sx) && (x3 >= ex) && (y4 <= sy) && (y4 >= ey)) flag |= 0x02 ;
break ;
}
// 第2象限
switch (pass[1]) {
default:
break ;
case 1:
flag |= 0x0C ;
break ;
case 2:
if ((x4 <= sx) && (y4 >= sy)) flag |= 0x04 ;
if ((x2 <= sx) && (y2 >= sy)) flag |= 0x08 ;
break ;
case 3:
if ((x4 >= ex) && (y4 <= ey)) flag |= 0x04 ;
if ((x2 >= ex) && (y2 <= ey)) flag |= 0x08 ;
break ;
case 4:
if (((x4 <= sx) || (x4 >= ex)) && ((y4 >= sy) || (y4 <= ey))) flag |= 0x04 ;
if (((x2 <= sx) || (x2 >= ex)) && ((y2 >= sy) || (y2 <= ey))) flag |= 0x08 ;
break ;
case 5:
if ((x4 <= sx) && (x4 >= ex) && (y4 >= sy) && (y4 <= ey)) flag |= 0x04 ;
if ((x2 <= sx) && (x2 >= ex) && (y2 >= sy) && (y2 <= ey)) flag |= 0x08 ;
break ;
}
// 第3象限
switch (pass[2]) {
default:
break ;
case 1:
flag |= 0x30 ;
break ;
case 2:
if ((x2 >= sx) && (y1 >= sy)) flag |= 0x10 ;
if ((x4 >= sx) && (y3 >= sy)) flag |= 0x20 ;
break ;
case 3:
if ((x2 <= ex) && (y1 <= ey)) flag |= 0x10 ;
if ((x4 <= ex) && (y3 <= ey)) flag |= 0x20 ;
break ;
case 4:
if (((x2 >= sx) || (x2 <= ex)) && ((y1 >= sy) || (y1 <= ey))) flag |= 0x10 ;
if (((x4 >= sx) || (x4 <= ex)) && ((y3 >= sy) || (y3 <= ey))) flag |= 0x20 ;
break ;
case 5:
if ((x2 >= sx) && (x2 <= ex) && (y1 >= sy) && (y1 <= ey)) flag |= 0x10 ;
if ((x4 >= sx) && (x4 <= ex) && (y3 >= sy) && (y3 <= ey)) flag |= 0x20 ;
break ;
}
// 第4象限
switch (pass[3]) {
default:
break ;
case 1:
flag |= 0xC0 ;
break ;
case 2:
if ((x3 >= sx) && (y3 <= sy)) flag |= 0x40 ;
if ((x1 >= sx) && (y1 <= sy)) flag |= 0x80 ;
break ;
case 3:
if ((x3 <= ex) && (y3 >= ey)) flag |= 0x40 ;
if ((x1 <= ex) && (y1 >= ey)) flag |= 0x80 ;
break ;
case 4:
if (((x3 >= sx) || (x3 <= ex)) && ((y3 <= sy) || (y3 >= ey))) flag |= 0x40 ;
if (((x1 >= sx) || (x1 <= ex)) && ((y1 <= sy) || (y1 >= ey))) flag |= 0x80 ;
break ;
case 5:
if ((x3 >= sx) && (x3 <= ex) && (y3 <= sy) && (y3 >= ey)) flag |= 0x40 ;
if ((x1 >= sx) && (x1 <= ex) && (y1 <= sy) && (y1 >= ey)) flag |= 0x80 ;
break ;
}
if (flag & 0x01) pset(win,x1,y2) ;
if (flag & 0x02) pset(win,x3,y4) ;
if (flag & 0x04) pset(win,x4,y4) ;
if (flag & 0x08) pset(win,x2,y2) ;
if (flag & 0x10) pset(win,x2,y1) ;
if (flag & 0x20) pset(win,x4,y3) ;
if (flag & 0x40) pset(win,x3,y3) ;
if (flag & 0x80) pset(win,x1,y1) ;
s -= 2 * dx + 1 ;
if (s < 0) {
--dy ;
s += 2 * dy ;
}
++dx ;
}
}
}
int main(int argc, char **argv)
{
int win;
gsetinitialattributes(DISABLE, BOTTOM_LEFT_ORIGIN); /*eggxの座標設定を通常のグラフィックスと同じに*/
win = gopen(400,400); /* 400x400 ピクセルのグラフィックス用ウィンドゥを開く */
newrgbcolor(win,255,0,0);
grArc(win,200,200,150,80,0,M_PI/3);
grArc(win,200,200,160,90,M_PI/3,M_PI*2/3);
grArc(win,200,200,170,100,M_PI*2/3,M_PI);
grArc(win,200,200,160,90,M_PI,M_PI*4/3);
grArc(win,200,200,170,100,M_PI*4/3,M_PI*5/3);
grArc(win,200,200,160,90,M_PI*5/3,0);
newrgbcolor(win,0,255,0);
grArc(win,200,200,100,150,0,M_PI);
grArc(win,200,200,50,100,M_PI,0);
grArc(win,200,200,75,125,M_PI/2,-M_PI/2);
newrgbcolor(win,0,0,200);
drawline(win,0,200,400,200);
drawline(win,200,0,200,400);
ggetch(); /* キー入力があるまで待つ */
gclose(win); /* グラフィックス用ウィンドゥを閉じる */
return 0;
}
実行結果
参考