2011-02-16 2 views
8

이전에는 Java 드로잉 메서드로 작업 해본 적이 없기 때문에 PoC로 살펴보고 아날로그 시계를 제작하기로 결정했습니다. 손에 더하여, 분/시간 동안 틱 마크가 포함 된 시계면을 그립니다. 나는 단순한 sin/cos 계산을 사용하여 원 주위의 선의 위치를 ​​결정합니다.Java - 서브 픽셀 라인 정확도에 AffineTransform이 필요합니까?

그러나 눈금이 매우 짧기 때문에 선의 각도가 잘못 표시됩니다. 이것은 Graphics2D.drawLine()Line2D.double() 방법 모두 서브 픽셀 정확도로 그릴 수 없기 때문입니다.

필자는 가운데에서 시작하여 원으로 마스킹하여 (더 길고 정확한 선을 만들기 위해) 선을 그릴 수 있음을 알고 있습니다.하지만 그와 같은 비싸지 않은 값 비싼 솔루션처럼 보입니다. 이 작업을 수행하는 방법에 대한 연구를 해봤지만 가장 좋은 대답은 AffineTransform입니다. 수퍼 샘플링을 수행하는 대신 반대로 AffineTransform을 사용할 수 있다고 가정합니다.

이 방법이 서브 픽셀 정밀도로 그리는 유일한 방법입니까? 아니면 잠재적으로 더 빠른 솔루션이 있습니까?

편집 : 나는 이미 Graphics2D 객체에 RenderingHint를 설정하고있다. 요청으로

, 여기에 코드를 약간 (이 단지의 PoC이었다으로 완벽하게 최적화되지 않음)입니다 :

diameter = Math.max(Math.min(pnlOuter.getSize().getWidth(), 
          pnlOuter.getSize().getHeight()) - 2, MIN_DIAMETER); 

for (double radTick = 0d; radTick < 360d; radTick += 6d) { 
    g2d.draw(new Line2D.Double(
     (diameter/2) + (Math.cos(Math.toRadians(radTick))) * diameter/2.1d, 
     (diameter/2) + (Math.sin(Math.toRadians(radTick))) * diameter/2.1d, 
     (diameter/2) + (Math.cos(Math.toRadians(radTick))) * diameter/2.05d, 
     (diameter/2) + (Math.sin(Math.toRadians(radTick))) * diameter/2.05d)); 
} // End for(radTick) 

여기 도면의 스크린 샷입니다. 보고는 다소 어려울 수 있지만 눈금을 59 분간보십시오. 완벽하게 수직입니다.

Sample image

+0

sc 시계를 계산/그리기위한 시계 및 코드의 reenshot 도움이 될 것입니다. –

답변

8

Line2D.double() 메소드는, 서브 픽셀 정밀도 을 그릴 수 없다. 형상 Line2D과 "서브 화소"정확도를 그릴 수 RenderingHints.VALUE_STROKE_PURE Graphics2D 문맥 객체를 사용하여 잘못된

.


나는 내가 수퍼 샘플링을 수행하는 데 반대 만 회전을 가진 AffineTransform를 사용할 수 있습니다 가정합니다. 정확도가 인 정확도가 서브 픽셀 인 그리기 방법입니까? 또는 잠재적으로 빠른 솔루션이 있습니까?

여기에 뭔가가 빠져 있다고 생각합니다. Graphics2D 객체는 이미 AffineTransform을 보유하고 있으며 모두 드로잉 작업과 저렴한 성능에 현명합니다.


하지만 당신의 코드에서 누락 된 것을 다시 연락하는 -이 누락되었습니다

screenshot :

g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, 
        RenderingHints.VALUE_STROKE_PURE); 
다음

는 자기가이 사진을 생성하는 예를 포함입니다

public static void main(String[] args) throws Exception { 

    final JFrame frame = new JFrame("Test"); 

    frame.add(new JComponent() { 
     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 

      Graphics2D g2d = (Graphics2D) g; 

      System.out.println(g2d.getTransform()); 
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
           RenderingHints.VALUE_ANTIALIAS_ON); 
      g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, 
           RenderingHints.VALUE_STROKE_PURE); 

      double dia = Math.min(getWidth(), getHeight()) - 2; 

      for (int i = 0; i < 60 ; i++) { 
       double angle = 2 * Math.PI * i/60; 
       g2d.draw(new Line2D.Double(
         (dia/2) + Math.cos(angle) * dia/2.1d, 
         (dia/2) + Math.sin(angle) * dia/2.1d, 
         (dia/2) + Math.cos(angle) * dia/2.05d, 
         (dia/2) + Math.sin(angle) * dia/2.05d)); 
      } 

      g2d.draw(new Ellipse2D.Double(1, 1, dia - 1, dia - 1)); 
     } 
    }); 

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(400, 400); 
    frame.setVisible(true); 
} 
+0

흠, 회전하는 것뿐 아니라 번역 (즉, 슈퍼 샘플링)해야하는 'AffineTransform'을 사용하고있는 것처럼 보입니다. 나는 이것을 현재 50ms마다 업데이트하고 있기 때문에 이것을 피하기를 바라고있다. –

+0

시계면을 별도로 그린 다음 변경 시계 손과 병합해서는 안됩니까? –

+0

@ D.N .: 오프라인 이미지 * 한 번만 만들 예정입니까? 매번 업데이트 할 때마다 만들어야합니까? (@ typo.pl : 예) – dacwe

관련 문제