円の一部(半円など)を塗る処理

   2012/11/17

Javaのグラフィックコマンドには、円(drawOval)や円塗り(fillOval)が
ありますが、drawOval(int x, int y, int width, int height);と
矩形の様な座標指定です(内接する円/楕円が描画されます)。

毎度、管理人イガジーです。

中心(x,y)と半径(r)を指定して描画したい時は

void drawCircle(int x, int y, int r) {
	g.fillOval(x-r, y-r, r*2, r*2);
}

というメソッドを使うと良いでしょう。

それはともかく、半円塗りや月の形塗りなど、
円の一部を塗る場合は自前で描画することになります。
半円を塗る場合は、例えば次のようなコードになるでしょう。

int r=120;
int x0=140; int y0=140;
for (int y=-r;y<=0;++y) {
	int x2;
//	x2=(int)Math.sqrt(r*r-y*y);
	double ac=Math.acos((double)y/(double)r);
	x2=(int)((double)r*Math.sin(ac)); // 円周
	g.setColor(Color.YELLOW);
	g.drawLine(x0, y0+y, x0+x2, y0+y);
	g.drawLine(x0, y0-y, x0+x2, y0-y);
	g.setColor(Color.DARK_GRAY);
	g.drawLine(x0-x2, y0+y, x0-1, y0+y);
	g.drawLine(x0-x2, y0-y, x0-1, y0-y);
}

ここで、(x0,y0)は、円の中心の座標です。
円周を表す数式は、x*x+y*y=r*r ですから
yを指定した時のxは、x=±sqr(r*r-y*y) で求められます。
あるいは、x=r*cos(α), y=r*sin(α) でもあるので
x=r*Math.sin(acos(y/r)); でも求められます。
どちらの式で計算しても結果は同じです。

半円を塗る場合は、中心線(x=0) から円周に向かって
線を引けば良いわけです。
三角関数など、doubleの演算回数は少ない方が良いので
y0+y の時の x座標(x2)を使って
y0-y の時の描画も行なってしまうのが効率的です。
同様に、必要なら x0+x2 と同時に x0-x2(反対側)の
塗り処理も行なってしまうのがよいでしょう。

月の形を描画する場合は

double age=4.8; // 月齢
double theta=Math.PI*age/14.765;
for (int y=-r;y<=0;++y) {
	int x2,x1;
//	x2=(int)Math.sqrt(r*r-y*y);
	double ac=Math.acos((double)y/(double)r);
	x2=(int)((double)r*Math.sin(ac)); // 円周
	x1=(int)((double)r*Math.cos(theta)*Math.sin(ac)); // 月の形
	if ((age>1.0)&&(age<29.0)) {
		if (age<15.0) {
			g.setColor(Color.YELLOW);
			g.drawLine(x0+x1, y0+y, x0+x2, y0+y);
			g.drawLine(x0+x1, y0-y, x0+x2, y0-y);
			g.setColor(Color.DARK_GRAY);
			g.drawLine(x0-x2, y0+y, x0+x1-1, y0+y);
			g.drawLine(x0-x2, y0-y, x0+x1-1, y0-y);
		}else{
			g.setColor(Color.YELLOW);
			g.drawLine(x0-x2, y0+y, x0-x1, y0+y);
			g.drawLine(x0-x2, y0-y, x0-x1, y0-y);
			g.setColor(Color.DARK_GRAY);
			g.drawLine(x0-x1-1, y0+y, x0+x2, y0+y);
			g.drawLine(x0-x1-1, y0-y, x0+x2, y0-y);
		}
	}else{
		g.setColor(Color.DARK_GRAY);
		g.drawLine(x0-x2, y0+y, x0+x2, y0+y);
		g.drawLine(x0-x2, y0-y, x0+x2, y0-y);
	}
}

という感じになるでしょう。
ここで、ageは月齢です。値を色々変えて試してみてください。

月齢1.0以下、および29.0以上は新月扱い(黄色い部分無し)
にしています。
これでそれっぽい月の形が描画できると思います。

この記事へのコメントはこちら

メールアドレスは公開されませんのでご安心ください。
また、* が付いている欄は必須項目となりますので、必ずご記入をお願いします。

内容に問題なければ、下記の「コメント送信」ボタンを押してください。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)