2010-02-14 14 views
12

मैं एक तरह से,, क्षेत्रफल की गणना करने java.awt.geom.Area की एक मनमाना उदाहरण के पिक्सल में रहा हूँ।java.awt.geom.Area के क्षेत्र की गणना कैसे करें?

पृष्ठभूमि: मेरे पास Shape है जो मेरे अनुप्रयोगों में ओवरलैप हो सकता है। मैं जानना चाहता हूं कि Shape कितना ओवरलैप करता है। Shape रों, विषम जा सकता है घुमाया, आदि अगर मैं एक समारोह area(Shape) (या Area), मैं तो जैसे दो Shape रों के चौराहे का उपयोग कर सकता था:

double fractionObscured(Shape bottom, Shape top) { 
    Area intersection = new Area(bottom); 
    intersection.intersect(new Area(top)); 
    return area(intersection)/area(bottom); 
} 
+0

क्यों डबल [] coords = new double [6]; और एक और सूचकांक का उपयोग नहीं किया जाता है? –

+0

आप बहुभुज चौराहे सूत्र घटता beizer को विस्तार करने के लिए सक्षम होना चाहिए। फिर आप सभी आकृतियों/क्षेत्रों के लिए सही क्षेत्रों को प्राप्त करने के लिए पथ इटरेटर्स का उपयोग कर सकते हैं। –

उत्तर

3

एक दृष्टिकोण fill() होगा प्रत्येक में वृद्धि की और transformedShape उपयुक्त AlphaComposite का उपयोग करके एक अलग रंग के साथ और अंतर्निहित Raster में ओवरलैपिंग पिक्सेल गिनें।

Addendum 1: का उपयोग AlphaComposite.Xor के प्रभाव को देखने के लिए दिखाता है कि किसी भी दो अपारदर्शी रंगों का अंतर शून्य है।

परिशिष्ट 2: पिक्सल की गणना करने में प्रदर्शन समस्याएं हो सकती हैं; नमूना मदद कर सकता है। यदि प्रत्येक Shape उचित रूप से उत्तल है, तो क्षेत्र के Shape एस 'getBounds2D() के क्षेत्रों के योग से ओवरलैप का अनुमान लगाना संभव हो सकता है। उदाहरण के लिए,

Shape s1, s2 ... 
Rectangle2D r1 = s1.getBounds2D(); 
Rectangle2D r2 = s2.getBounds2D(); 
Rectangle2D r3 = new Rectangle2D.Double(); 
Rectangle2D.intersect(r1, r2, r3); 
double overlap = area(r3)/(area(r1) + area(r2)); 
... 
private double area(Rectangle2D r) { 
    return r.getWidth() * r.getHeight(); 
} 

आप अनुभव परिणाम मान्य करना पड़ सकता है।

+0

छवि के रास्टराइजिंग भाग के विकल्पों को इंगित करने और वास्तविक नमूना मूल्यों को देखने के लिए धन्यवाद। – iter

+0

मुझे लगता है कि यह अधिक सटीक है, लेकिन मैंने एक संभावित तेज़ विकल्प भी सुझाया जो पर्याप्त हो सकता है। – trashgod

11

निम्नलिखित स्निपेट का उपयोग कर एक बहुभुज का क्षेत्रफल ज्ञात करने के लिए: यहाँ

int sum = 0; 
for (int i = 0; i < n -1; i++) 
{ 
    sum = sum + x[i]*y[i+1] - y[i]*x[i+1]; 
} 
// (sum/2) is your area. 
System.out.println("The area is : " + (sum/2)); 

n कोने और एक्स [i] और y [i] की कुल संख्या एक्स और एक शीर्ष के y निर्देशांक कर रहे हैं मैं। ध्यान दें कि इस एल्गोरिदम के लिए काम करने के लिए, बहुभुज बंद होना चाहिए। यह खुले बहुभुज पर काम करता है।

आप बहुभुज here से संबंधित गणितीय अलोग्रिदम पा सकते हैं। आपको इसे स्वयं कोड में बदलने की आवश्यकता है :)

+0

लिंक के लिए धन्यवाद। यह एक मान्य दृष्टिकोण है, लेकिन एक दिशा नहीं जिसमें मैं जाना चाहता हूं। 'आकार में वक्र खंड शामिल हो सकते हैं और अन्य आकारों की रचनाएं हो सकती हैं।मेरे लिए अनुसरण करने के लिए गणित बहुत बालों वाली हो जाती है। – iter

+3

@iter, आप पॉलीगॉन के रूप में वक्र अनुमानित करने के लिए 'GetPathIterator (AffineTransform, डबल flatness)' का उपयोग कर सकते हैं। इसके अलावा 'एरिया' कन्स्ट्रक्टर आकार को गैर-आत्म-अंतरण घटकों में विघटित कर देंगे, इसलिए यदि आप इसे 'पथइटरेटर' का उपयोग करने के लिए अनुकूलित करते हैं तो यह एल्गोरिदम काम करेगा। – finnw

+0

देखें http://stackoverflow.com/a/22910330/798223 – GKFX

6

मैंने इस वर्ग का उपयोग अपनी परियोजनाओं में से किसी एक आकार के अनुमान के अनुमान के लिए किया है। यह धीमी है लेकिन उच्च संकल्प में यह अभी भी पिक्सल गिनती की तुलना में तेजी हो सकता है (क्योंकि पिक्सल गिनती की लागत संकल्प के साथ quadratically होती है, लेकिन परिधि पर रेखा खंडों की संख्या रैखिक बढ़ता है।)

import static java.lang.Double.NaN; 

import java.awt.geom.AffineTransform; 
import java.awt.geom.Area; 
import java.awt.geom.FlatteningPathIterator; 
import java.awt.geom.Line2D; 
import java.awt.geom.PathIterator; 

public abstract class Areas { 
    public static double approxArea(Area area, double flatness, int limit) { 
     PathIterator i = 
      new FlatteningPathIterator(area.getPathIterator(identity), 
             flatness, 
             limit); 
     return approxArea(i); 
    } 

    public static double approxArea(Area area, double flatness) { 
     PathIterator i = area.getPathIterator(identity, flatness); 
     return approxArea(i); 
    } 

    public static double approxArea(PathIterator i) { 
     double a = 0.0; 
     double[] coords = new double[6]; 
     double startX = NaN, startY = NaN; 
     Line2D segment = new Line2D.Double(NaN, NaN, NaN, NaN); 
     while (! i.isDone()) { 
      int segType = i.currentSegment(coords); 
      double x = coords[0], y = coords[1]; 
      switch (segType) { 
      case PathIterator.SEG_CLOSE: 
       segment.setLine(segment.getX2(), segment.getY2(), startX, startY); 
       a += hexArea(segment); 
       startX = startY = NaN; 
       segment.setLine(NaN, NaN, NaN, NaN); 
       break; 
      case PathIterator.SEG_LINETO: 
       segment.setLine(segment.getX2(), segment.getY2(), x, y); 
       a += hexArea(segment); 
       break; 
      case PathIterator.SEG_MOVETO: 
       startX = x; 
       startY = y; 
       segment.setLine(NaN, NaN, x, y); 
       break; 
      default: 
       throw new IllegalArgumentException("PathIterator contains curved segments"); 
      } 
      i.next(); 
     } 
     if (Double.isNaN(a)) { 
      throw new IllegalArgumentException("PathIterator contains an open path"); 
     } else { 
      return 0.5 * Math.abs(a); 
     } 
    } 

    private static double hexArea(Line2D seg) { 
     return seg.getX1() * seg.getY2() - seg.getX2() * seg.getY1(); 
    } 

    private static final AffineTransform identity = 
     AffineTransform.getQuadrantRotateInstance(0); 
} 
2

मैं टिप्पणी होगा अगर मैं कर सकता। सूरज, अपने एल्गोरिथ्म सही है, लेकिन कोड

 int sum = 0; 
     for (int i = 0; i < npoints ; i++) 
     { 
      sum = sum + Xs[i]*Ys[(i+1)%npoints] - Ys[i]*Xs[(i+1)%npoints]; 
     } 

     return Math.abs(sum/2); 

अपने कोड में पिछले vertice को ध्यान में रखा नहीं है होना चाहिए। बस एक छोटा सा संपादन :)

संबंधित मुद्दे