문제

높이와 너비가 동일한 메소드 도로를 사용해 보았지만 직경이 높아짐에 따라 원은 악화됩니다. 크기에 상관없이 괜찮은 원을 갖기 위해 무엇을 할 수 있습니까? Java 또는 다른 방법에서 반 알리 아싱을 어떻게 구현합니까?

도움이 되었습니까?

해결책

결과적으로, 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);

도움이 될 수있는 두 가지 :

  1. 사용 Graphics2D.draw(Shape) 인스턴스와 함께 java.awt.geom.Ellipse2D 대신에 Graphics.drawOval
  2. 결과가 여전히 만족스럽지 않은 경우 사용해보십시오. 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);
}

예를 들어 Josef의 답변을 참조하십시오 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);
}

버그 보고서를 지적한 Oleg Estekhin에게 감사합니다. 버그 보고서를 지적하는 방법을 설명하기 때문입니다.

다음은 전후에 작은 원입니다. 픽셀 그리드를보기 위해 몇 번 확대되었습니다.

Circles before and after

줄을 내려 가면 서브 픽셀 금액으로 약간 움직입니다.

첫 번째 열은 힌트를 렌더링하지 않습니다. 두 번째는 antialias 만 있습니다. 세 번째는 안티 리아와 순수한 모드입니다.

antialias 힌트만으로 처음 3 개의 원이 동일하고 마지막 두 원도 동일합니다. 불연속 전환이 발생하는 것 같습니다. 아마도 어느 시점에서 반올림.

코드는 다음과 같습니다. 그것은 가독성을 위해 Jython에 있지만, Java 런타임 라이브러리를 아래로 구동하고 정확히 동일한 효과로 동등한 Java 소스로 무자비하게 포팅 될 수 있습니다.

from java.lang import *
from java.io import *
from java.awt import *
from java.awt.geom import *
from java.awt.image import *
from javax.imageio import *

bim = BufferedImage(30, 42, BufferedImage.TYPE_INT_ARGB)
g = bim.createGraphics()
g.fillRect(0, 0, 100, 100)
g.setColor(Color.BLACK)
for i in range(5):
    g.draw(Ellipse2D.Double(2+0.2*i, 2+8.2*i, 5, 5))

g.setRenderingHint( RenderingHints.  KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON)

for i in range(5):
    g.draw(Ellipse2D.Double(12+0.2*i, 2+8.2*i, 5, 5))

g.setRenderingHint( RenderingHints.  KEY_STROKE_CONTROL,
                    RenderingHints.VALUE_STROKE_PURE)

for i in range(5):
    g.draw(Ellipse2D.Double(22+0.2*i, 2+8.2*i, 5, 5))

#You'll probably want this too later on:
#g.setRenderingHint( RenderingHints.  KEY_INTERPOLATION,
#                    RenderingHints.VALUE_INTERPOLATION_BICUBIC)
#g.setRenderingHint( RenderingHints.  KEY_RENDERING, 
#                    RenderingHints.VALUE_RENDER_QUALITY)

ImageIO.write(bim, "PNG", File("test.png"))

요약 : 둘 다 필요합니다 VALUE_ANTIALIAS_ON 그리고 VALUE_STROKE_PURE 서브 픽셀 정확도로 그려진 적절한 원을 얻으려면.

"괜찮은 원형 원"을 그릴 수없는 것은 매우 오래된 버그와 관련이 있습니다. 6431487.

항아리아를 켜는 것은 많은 도움이되지 않습니다. 필요한 원 크기가 16 픽셀 (아이콘 크기에 여전히 일반적으로 일반적)이고 항아리아 링이 켜져있을 때 Drawoval () 또는 Drawshape (Eclipse)가 생성 한 "원"의 종류를 확인하십시오. 더 큰 antialiased 서클은 더 좋아 보일 것이지만 누군가가 그들을 자세히 보려고한다면 여전히 비대칭입니다.

"괜찮은 모습의 원"을 그려 보는 것은 수동으로 하나를 그리는 것이 필요한 것 같습니다. 항아리아를 사용하지 않으면 MidPoint Circle 알고리즘이됩니다 (이것은 의문 예쁜 Java 코드로 답이 있습니다).

편집 : 2017 년 9 월 6 일

그것은 정수 매트릭스 위에 원을 그리기 위해 저에 의해 발명 된 알고리즘입니다. 동일한 아이디어를 사용하여 BufferedImage 내부에 원을 쓸 수 있습니다. 클래스 그래픽을 사용하여 원을 그려 보려고한다면 이것은 당신이 찾고있는 응답이 아닙니다 (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;
}

수동으로 정확성을 확인하면서 여러 번 시도해 보았으므로 작동한다고 생각합니다. 코드를 단순화하기 위해 범위 점검을하지 않았습니다. 나는 그것이 당신과 모든 사람들이 매트릭스 위에 원을 그리는 데 도움이되기를 바랍니다. 게임 맵 [도움이 필요하면 이메일을 이메일로 보내십시오).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top