2011-02-16 9 views
8

Daha önce hiç Java çizim yöntemleri ile çalışmadım, bu yüzden bir PoC olarak analog bir saat oluşturmaya ve oluşturmaya karar verdim. Ellere ek olarak, dakika/saat için onay işaretlerini içeren bir saat yüzü çiziyorum. Dairenin çevresindeki çizgilerin konumunu belirlemek için basit sin/cos hesaplamaları kullanırım.Java - Alt piksel doğruluk oranı bir AffineTransform gerektirir mi?

Ancak, dakika kene-işaretleri beri çok kısadır, çizgilerin açısı yanlış göründüğünü fark etmiş. Bunun nedeni, hem Graphics2D.drawLine() hem de Line2D.double() yöntemlerinin subpixel doğruluğu ile çizilememesidir.

I (daha doğru çizgiler daha oluşturmak için) merkezinden çıkan ve bir daire ile maskeleyerek çizgiler çizmek biliyorum, ama böyle bir kaba ve pahalı bir çözüm gibi görünmektedir. Bunu nasıl yapacağım konusunda biraz araştırma yaptım, ama karşılaştığım en iyi cevap bir AffineTransform kullanmak. Bir supersampling yapmak zorunda kalmanın aksine, sadece AffineTransform kullanabileceğimi farz ediyorum.

bu alt piksel doğrulukla çizim tek/en iyi yöntem var mı? Ya da potansiyel olarak daha hızlı bir çözüm var mı?

Düzenleme: Zaten Graphics2D nesneye bir RenderingHint kuruyorum. İstendiği gibi

, burada kod biraz (bu sadece bir PoC olarak tam olarak optimize edilmemiş) 'dir:

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) 

İşte çizimin bir ekran var. Görmek biraz zor olabilir ama 59 dakika için onay işaretine bakın. Mükemmel dikey.

Sample image

+0

sc saatin tekrar hesaplanması ve saatin hesaplanması/çizilmesi yardımcı olacaktır. –

cevap

8

Line2D.double() yöntemleri alt piksel hassasiyetle çekemez. şekil Line2D ile "alt piksel" doğruluğu çizebilir RenderingHints.VALUE_STROKE_PURE Graphics2D nesne kullanılarak yanlış

.


Ben SuperSampling gerçekleştirmek zorunda için aksine, sadece rotasyon içeren bir AffineTransform kullanabilirsiniz varsayalım. Bu alt piksel doğruluk ile çizim en iyi/en iyi mi? Yoksa daha hızlı bir çözüm var mı?

Burada somthing eksik olduğunu düşünüyorum. Graphics2D nesnesi zaten bir AffineTransform tutuyor ve tüm çizim eylemleri ve ucuz performans açısından kullanıyor.


Ama kod eksik olan şeyi size geri almak için - bu eksik:

screenshot:

g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, 
        RenderingHints.VALUE_STROKE_PURE); 
Aşağıda

kendinden bu resmi üretir örnek yeten

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

Hmm, görünür bir * AffineTransform' kullanıyorsunuz *, * çevirmek (yani, supersample) ve döndürmek zorunda. Bunu önlemek için umuyordum, şu anda her 50 ms'de bir güncelleme yapıyor. –

+0

Saat yüzünü ayrı ayrı çizmemeniz ve sonra değişen saatli ellerle birleştirmeniz gerekmiyor mu? –

+0

@ D.N .: Sadece çevrimdışı görüntü oluşturuyorum * bir kez *? Her güncellemeyi oluşturmanız mı gerekiyor? (@ typo.pl: evet) – dacwe

İlgili konular