2011-02-16 29 views
8

मैंने पहले जावा ड्राइंग विधियों के साथ कभी काम नहीं किया है, इसलिए मैंने पीओसी के रूप में एनालॉग घड़ी में गोता लगाने और बनाने का फैसला किया। हाथों के अलावा, मैं एक घड़ी का चेहरा खींचता हूं जिसमें मिनट/घंटे के लिए टिक अंक शामिल होते हैं। मैं सर्कल के चारों ओर की रेखाओं की स्थिति निर्धारित करने के लिए सरल पाप/कोस गणना का उपयोग करता हूं।जावा - क्या उप-पिक्सेल लाइन सटीकता को एफ़िनट्रांसफॉर्म की आवश्यकता होती है?

हालांकि, मैंने देखा है कि चूंकि मिनट टिक टिक बहुत कम हैं, लाइनों का कोण गलत दिखता है। मुझे यकीन है कि यह इसलिए है क्योंकि 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) 

यहाँ ड्राइंग का एक स्क्रीनशॉट है। यह देखना मुश्किल हो सकता है, लेकिन 5 9 मिनट के लिए टिक मार्क देखें। यह पूरी तरह लंबवत है।

Sample image

+0

स्क घड़ी की गणना/घड़ी के लिए घड़ी और कोड का पुन: शॉट मदद करेगा। –

उत्तर

8

Line2D.double() पद्धतियों उपपिक्सेल सटीकता के साथ आकर्षित नहीं कर सकता।

गलत, RenderingHints.VALUE_STROKE_PURE Graphics2D वस्तु का उपयोग कर आकार Line2D साथ आकर्षित कर सकते हैं "उपपिक्सेल" सटीकता।


मुझे लगता है मैं एक supersampling प्रदर्शन करने के लिए होने के लिए केवल रोटेशन के साथ एक AffineTransform इस्तेमाल कर सकते हैं विपरीत, मान लें। क्या यह सब-पिक्सेल सटीकता के साथ ड्राइंग की एकमात्र/सर्वोत्तम विधि है? या क्या कोई संभावित तेज समाधान है?

मुझे लगता है कि आप यहां कुछ खो रहे हैं। ग्राफिक्स 2 डी ऑब्जेक्ट में पहले से ही 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' का उपयोग कर रहे हैं जो * * * अनुवाद करना है (यानी supersample) साथ ही घूमना। मैं इस से बचने की उम्मीद कर रहा हूं, क्योंकि वर्तमान में यह हर 50 एमएमएस को अपडेट कर रहा है। –

+0

क्या आप घड़ी के चेहरे को अलग से नहीं खींचते हैं और फिर इसे बदलने वाले घड़ी के हाथों में विलय करना चाहिए? –

+0

@ डीएन .: मैं केवल ऑफ़लाइन छवि * एक बार * बना रहा हूं? क्या आपको इसे हर अद्यतन बनाने की ज़रूरत है? (@ typo.pl: yes) – dacwe