![](/img/trans.png)
[英]NotSerializableException with java.awt.geom.Area
[英]How to calculate the area of a java.awt.geom.Area?
我正在尋找一種方法來計算java.awt.geom.Area
的任意實例的面積(以像素為單位)。
背景:我的應用程序中有可能重疊的Shape
。 我想知道一個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);
}
要使用以下代碼段查找多邊形的面積:
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);
}
一種方法是使用合適的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();
}
您可能需要憑經驗驗證結果。
如果可以,我會發表評論。 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);
在您的代碼中,不考慮最后一個頂點。 只是一個小的編輯:)
給出的答案不准確,我發現以下解決方案提供了更好的結果
private int calcAreaSize(Area area){
int sum = 0;
float xBegin=0, yBegin=0, xPrev=0, yPrev=0, coords[] = new float[6];
for (PathIterator iterator1 = area.getPathIterator(null, 0.1); !iterator1.isDone(); iterator1.next()){
switch (iterator1.currentSegment(coords))
{
case PathIterator.SEG_MOVETO:
xBegin = coords[0]; yBegin = coords[1];
break;
case PathIterator.SEG_LINETO:
// the well-known trapez-formula
sum += (coords[0] - xPrev) * (coords[1] + yPrev) / 2.0;
break;
case PathIterator.SEG_CLOSE:
sum += (xBegin - xPrev) * (yBegin + yPrev) / 2.0;
break;
default:
// curved segments cannot occur, because we have a flattened ath
throw new InternalError();
}
xPrev = coords[0]; yPrev = coords[1];
}
return sum;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.