12
votes

Comment calculer la zone d'un java.awt.geom.area?

Je cherche un moyen de calculer la zone, en pixels, d'une instance arbitraire de java.awt.geom.area .

L'arrière-plan: j'ai forme < / code> S dans mes applications pouvant se chevaucher. Je veux savoir à quel point un forme chevauche une autre. La forme s peut être asymétrique, tournée, etc. Si j'avais une fonction de la zone (ou zone ), je pourrais utiliser le Intersection de deux forme s comme: xxx


2 commentaires

pourquoi doubler [] coordiens = nouveau double [6]; Et pas un autre index est utilisé?


Vous devriez être capable d'étendre la formule d'intersection du polygone aux courbes Bezier. Ensuite, vous pouvez utiliser des itérateurs de chemins pour obtenir des zones proches de toutes les formes / zones.


5 Réponses :


3
votes

Une approche serait de remplissage () chacun échelonné et transformé forme avec une couleur différente à l'aide d'un alphacomposite et comptez les pixels qui se chevauchent dans le sous-jacent raster .

addendum 1: Utilisation de cette Calculatrice pour voir l'effet de alphacomposite.xor montre que l'interssertion de Toutes deux couleurs opaques sont zéro.

Addendum 2: Compter les pixels peuvent avoir des problèmes de performance; L'échantillonnage peut aider. Si chaque forme est raisonnablement convexe, il peut être possible d'estimer le chevauchement du rapport du intersect () < / a> zone à la somme des zones du forme s ' getbounds2d () . Par exemple, xxx

Vous devrez peut-être valider les résultats empiriquement.


2 commentaires

Merci d'avoir souligné les options de rasterizing une partie de l'image et de la recherche de valeurs d'échantillonnage réelles.


Je pense que c'est plus précis, mais j'ai aussi suggéré une alternative potentiellement plus rapide qui pourrait être suffisante.



12
votes

Pour trouver la zone d'un polygone à l'aide de l'extrait suivant: xxx

ici n est le nombre total de sommets et x [i] et y [i] sont les coordonnées x et y. d'un sommet i. Notez que pour que cet algorithme fonctionne, le polygone doit être fermé. Il fonctionne sur des polygones ouverts.

Vous pouvez trouver des alogrits mathématiques liés aux polygones ici . Vous devez le convertir en Code vous-même :)


2 commentaires

Merci pour le lien. Ceci est une approche valide, mais pas une direction que je veux entrer. La forme S peut inclure des segments de courbe et peut être des compositions d'autres formes. Les maths deviennent trop velus pour que je puisse suivre.


@iter, vous pouvez utiliser un getPathiterator (affinetransform at, double planéité) pour se rapprocher de la courbe en tant que polygone. De plus, les constructeurs décomposeront la forme dans des composants non auto-interssers, de sorte que cet algorithme fonctionnera si vous l'adaptez pour utiliser un pathiterator .



6
votes

J'ai utilisé cette classe pour se rapprocher de la zone d'une forme dans l'un de mes projets. Il est lent mais à haute résolution, il peut encore être plus rapide que de compter des pixels (car le coût de comptage des pixels augmente quadratique avec la résolution, mais le nombre de segments de ligne sur le périmètre augmente linéairement.)

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


0 commentaires

3
votes

Je commenterais si je pouvais. Suraj, votre algorithme est correct, mais le code doit être xxx

dans votre code, la dernière vertice n'est pas prise en compte. Juste une petite édition :)


0 commentaires

0
votes

La réponse donnée n'est pas exacte, j'ai constaté que, après Solution donne de nombreux résultats meilleurs

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


0 commentaires