Как рассчитать площадь java.awt.geom.Area? - PullRequest
12 голосов
/ 15 февраля 2010

Я ищу способ вычисления площади в пикселях произвольного экземпляра java.awt.geom.Area.

Фон: у меня есть Shape s в моих приложениях, которые могут перекрываться. Я хочу знать, насколько одно Shape перекрывает другое. Shape s может быть перекошен, повернут и т. Д. Если бы у меня была функция area(Shape) (или Area), я мог бы использовать пересечение двух Shape s следующим образом:

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

Ответы [ 4 ]

11 голосов
/ 15 февраля 2010

Чтобы найти площадь многоугольника, используйте следующий фрагмент:

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] - координаты x и y вершины i. Обратите внимание, что для работы этого алгоритма полигон должен быть закрыт. Это работа над открытыми полигонами.

Здесь вы можете найти математические алогриты, связанные с полигонами здесь . Вам нужно конвертировать его в код самостоятельно:)

6 голосов
/ 15 февраля 2010

Я использовал этот класс для аппроксимации площади фигуры в одном из моих проектов. Он медленный, но при высоком разрешении он все же может быть быстрее, чем подсчет пикселей (поскольку стоимость подсчета пикселей растет квадратично с разрешением, а количество линейных сегментов по периметру растет линейно.)

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);
}
3 голосов
/ 15 февраля 2010

Одним из подходов будет fill() каждый масштабированный и преобразованный Shape с другим цветом с использованием подходящего AlphaComposite и подсчитайте перекрывающиеся пиксели в базовом 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();
}

Возможно, вам потребуется подтвердить результаты эмпирически.

2 голосов
/ 07 апреля 2014

Я бы прокомментировал, если бы мог. Сурадж, твой алгоритм правильный, но код должен быть

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

В вашем коде последняя вершина не учитывается. Просто небольшая правка:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...