高さと幅が同じメソッド drawOval を使用してみましたが、直径が大きくなると円の見栄えが悪くなります。サイズに関係なく、見栄えのする円を作成するにはどうすればよいですか。Javaまたはその他の方法でアンチエイリアスを実装するにはどうすればよいですか。
7 に答える
結局のところ、Java2D (あなたが使っているのは Java2D だと思います) は、すでにこの点でかなり優れています! ここにまともなチュートリアルがあります: http://www.javaworld.com/javaworld/jw-08-1998/jw-08-media.html
重要な行は次のとおりです。
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
レンダリングのヒントを設定できます:
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
役立つ可能性のある2つのこと:
- の代わりにの
Graphics2D.draw(Shape)インスタンスで使用しますjava.awt.geom.Ellipse2DGraphics.drawOval - それでも満足のいく結果が得られない場合は、 を使用
Graphics2D.setRenderingHintしてアンチエイリアシングを有効にしてみてください
例
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Shape theCircle = new Ellipse2D.Double(centerX - radius, centerY - radius, 2.0 * radius, 2.0 * radius);
g2d.draw(theCircle);
}
例については、ジョセフの回答を参照してくださいsetRenderingHint
もちろん、半径を必要なものに設定します。
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
Ellipse2D.Double hole = new Ellipse2D.Double();
hole.width = 28;
hole.height = 28;
hole.x = 14;
hole.y = 14;
g2d.draw(hole);
}
「まともな円」を描画できないのは、非常に古いバグ6431487に関連しています。
アンチエイリアシングをオンにしてもあまり役に立ちません。必要な円のサイズが 16 ピクセル (アイコン サイズではまだかなり一般的) で、アンチエイリアシングがオンの場合に、 drawOval() または drawShape(Eclipse) によって生成される「円」の種類を確認するだけです。アンチエイリアス処理された円が大きいほど見栄えは良くなりますが、誰かがそれらをよく見ると気になる場合は、依然として非対称です。
「まともな円」を描くには、手動で描く必要があるようです。アンチエイリアシングなしでは、ミッドポイント サークル アルゴリズムになります (この質問には、かなりの Java コードで回答があります)。
編集日: 2017 年 9 月 6 日
これは、整数行列上に円を描くために私が発明したアルゴリズムです。同じ考え方を使用して、BufferedImage 内に円を書き込むことができます。クラスGraphicsを使用してその円を描画しようとしている場合、これは探している答えではありません(g.drawLine(x、y、x + 1、y)で各色の割り当てを変更したい場合を除きますが、可能です)非常に遅くなります)。
protected boolean runOnCircumference(int[][] matrix, int x, int y, int ray, int color) {
boolean ret;
int[] rowUpper = null, rowInferior = null, rowCenterUpper = null, rowCenterInferior = null;
if (ret = ray > 0) {
if (ray == 1) {
matrix[y][x + 1] = color;
rowUpper = matrix[++y];
rowUpper[x] = color;
rowUpper[x + 2] = color;
matrix[y][x] = color;
} else {
double rRay = ray + 0.5;
int r = 0, c = 0, ray2 = ray << 1, ray_1 = ray - 1, halfRay = (ray >> 1) + ray % 2, rInf,
ray1 = ray + 1, horizontalSymmetricOldC;
// draw cardinal points
rowUpper = matrix[ray + y];
rowUpper[x] = color;
rowUpper[x + ray2] = color;
matrix[y][x + ray] = color;
matrix[ray2 + y][x + ray] = color;
horizontalSymmetricOldC = ray1;
rInf = ray2;
c = ray_1;
for (r = 0; r < halfRay; r++, rInf--) {
rowUpper = matrix[r + y];
rowInferior = matrix[rInf + y];
while (c > 0 && (Math.hypot(ray - c, (ray - r)) < rRay)) {
rowUpper[x + c] = color;
rowUpper[x + horizontalSymmetricOldC] = color;
rowInferior[x + c] = color;
rowInferior[x + horizontalSymmetricOldC] = color;
// get the row pointer to optimize
rowCenterUpper = matrix[c + y];
rowCenterInferior = matrix[horizontalSymmetricOldC + y];
// draw
rowCenterUpper[x + r] = color;
rowCenterUpper[x + rInf] = color;
rowCenterInferior[x + r] = color;
rowCenterInferior[x + rInf] = color;
horizontalSymmetricOldC++;
c--;
}
} // end r circle
}
}
return ret;
}
手動で正しいことを確認しながら何度も試したので、うまくいくと思います。コードを単純化するためだけに、範囲チェックは行っていません。これが、マトリックス上に円を描きたいと考えている皆さんの助けになれば幸いです (たとえば、純粋なコードで独自のビデオゲームを作成しようとしていて、マトリックス指向のゲーム マップを管理してオブジェクトをテーブルに格納する必要があるプログラマーなど)。 game-map [これについてサポートが必要な場合は、私にメールしてください])。