如何计算java.awt.geom.Area的区域?

我正在寻找一种方法来计算java.awt.geom.Area的任意实例的面积(以像素为单位)。

背景:我的应用程序中的Shape可能会重叠。 我想知道一个Shape与另一个Shape重叠多少。 Shape s可能会倾斜,旋转等。如果我有一个functionarea(Shape) (或Area ),我可以使用两个Shape的交集,如下所示:

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

一种方法是使用合适的AlphaComposite以不同的颜色fill()每个缩放和变换的 Shape ,并计算底层Raster的重叠像素。

附录1:使用此计算器查看AlphaComposite.Xor的效果,显示任意两种不透明颜色的交点为零。

附录2:计数像素可能存在性能问题; 抽样可能有所帮助 如果每个Shape都是合理凸的,则可以根据intersect()区域与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(); } 

您可能需要根据经验validation结果。

要使用以下代码段查找多边形的区域:

 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是顶点的总数,x [i]和y [i]是顶点i的x和y坐标。 请注意,要使此算法起作用,必须关闭多边形。 它开放多边形的工作。

你可以在这里找到与多边形相关的数学算法。 您需要将其转换为代码自己:)

我已经使用这个类来近似我的一个项目中的形状区域。 它很慢但是在高分辨率下它可能仍然比计算像素更快(因为计数像素的成本随着分辨率的增加而呈二次方增长,但周长上的线段数量呈线性增长。)

 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); } 

如果可以,我会评论。 Suraj,你的算法是正确的,但代码应该是

  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); 

在您的代码中,不考虑最后一个顶点。 只是一个小编辑:)