Package fmg.fmg8.graphVis.zeichenModi

Source Code of fmg.fmg8.graphVis.zeichenModi.Polygon2D

/*
* Dateiname:        Polygon2D.java
* Autor(en):        Lukas K�nig
* Java-Version:     6.0
* Letzte Aenderung: 19.12.2008
*
* (c) Lukas K�nig, die Datei unterliegt der LGPL
* -> http://www.gnu.de/lgpl-ger.html
*/

package fmg.fmg8.graphVis.zeichenModi;

import java.awt.Polygon;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import fmg.fmg8.sonstiges.SonstMeth;
import fmg.fmg8.statistik.Parametersatz;
import fmg.fmg8.umgebung2D.Vektor2D;


/**
* Implementierung eines Polygons.
*
* @author Lukas K�nig
*/
public class Polygon2D extends ArrayList<Vektor2D> {

    /**
     * Die X-Werte der Punkte.
     */
    private ArrayList<Double> xPoints;
   
    /**
     * Die Y-Werte der Punkte.
     */
    private ArrayList<Double> yPoints;
   
    /**
     * Umschlie�endes Rechteck.
     */
    private Rechteck2D boundingBox;
   
    /**
     * Flag, mit dem garantiert werden kann, dass ein Punkt nur hinzugef�gt
     * werden kann, wenn das Polygon dadurch einfach bleibt.
     */
    private boolean garantiereEinfach;
   
    /**
     * Die Parameter.
     */
    private Parametersatz pars;
   
    /**
     * Die UID.
     */
    private static final long serialVersionUID = -8522419836028979412L;

    /**
     * Konstruktor aus Vaterklasse.
     */
    public Polygon2D() {
        super();
        this.xPoints = new ArrayList<Double>();
        this.yPoints = new ArrayList<Double>();
    }

    /**
     * Konstruktor aus Vaterklasse.
     *
     * @param initialCapacity  Mit initialer Kapazit�t.
     */
    public Polygon2D(final int initialCapacity) {
        super(initialCapacity);
        this.xPoints = new ArrayList<Double>(initialCapacity);
        this.yPoints = new ArrayList<Double>(initialCapacity);
    }
   
    /**
     * Konstruktor aus Vaterklasse.
     *
     * @param c  Aus Collektion.
     */
    public Polygon2D(final Collection< ? extends Vektor2D> c) {
        super(c);
        throw new RuntimeException("Konstruktor noch nicht definiert.");
    }

    /**
     * Berechnet einen Schnittpunkt der Strecke s1 mit dem Polygon, falls es
     * einen gibt.
     *
     * @param s1  Die Strecke.
     *
     * @return  Ein Schnittpunkt der Strecke mit dem Polygon, falls einer
     *          vorhanden ist, <code>null</code> sonst.
     */
    public Vektor2D schneidet(final Strecke2D s1) {
        Strecke2D s2
            = new Strecke2D(this.get(this.nPoints() - 1), this.get(0));
        boolean flip = false;
        Vektor2D schnitt;
       
        for (int i = 1; i <= this.nPoints(); i++) {
            schnitt = s1.schnPkt(s2);
           
            if (schnitt != null) {
                return schnitt;
            }

            if (flip && i < this.nPoints()) {
                s2.setEndPkt(this.get(i));
            } else if (i < this.nPoints()) {
                s2.setAnfPkt(this.get(i));
            }
           
            flip = !flip;
        }
       
        return null;
    }
   
    /**
     * F�gt einen Punkt ans Ende des Polygons.
     *
     * @param punkt  Der einzuf�gende Punkt.
     *
     * @return  Ob ein Element eingef�gt wurde.
     */
    @Override
    public boolean add(final Vektor2D punkt) {
        this.add(this.nPoints(), punkt);
        return true;
    }
   
    /**
     * F�gt einen Punkt an einer bestimmten Stelle zum Polygon hinzu.
     *
     * Wenn Einfachheit erzwungen wird, dann wird gepr�ft, ob die beiden
     * neuen Strecken, die zum Polygon durch den Punkt hinzukommen w�rden,
     * das Polygon schneiden und in diesem Fall der Punkt ignoriert.
     *
     * @param index    Der Index des Elements.
     * @param punkt  Das einzuf�gende Element.
     */
    @Override
    public void add(final int index, final Vektor2D punkt) {
        Strecke2D s1;
        Strecke2D s2;
       
        if (this.garantiereEinfach && this.nPoints() > 2) {
            s1 = new Strecke2D(this.get(index - 1), punkt);
            if (index < this.nPoints()) {
                s2 = new Strecke2D(punkt, this.get(index));
            } else {
                s2 = new Strecke2D(punkt, this.get(0));
            }
           
            if (this.schneidet(s1) != null || this.schneidet(s2) != null) {
                if (this.pars != null) {
                    SonstMeth.log(SonstMeth.LOG_DEBUG,
                                  "Punkt nicht eingefuegt: " + punkt,
                                  this.pars);
                }
               
                return;
            }
        }
       
        super.add(index, punkt);

        this.xPoints.add(index, punkt.x);
        this.yPoints.add(index, punkt.y);
       
        if (this.getBoundingBox() == null) {
            this.createBoundingBox();
        } else {
            this.erweitereBoundingBox(punkt);
        }
    }

    /**
     * Erzeugt den umschlie�enden Rahmen neu.
     */
    private void createBoundingBox() {
        if (this.nPoints() == 0) {
            return;
        }
       
        Vektor2D punkt = this.get(0);
       
        this.boundingBox = new Rechteck2D(punkt, punkt);
       
        for (int i = 1; i < this.nPoints(); i++) {
            this.erweitereBoundingBox(this.get(i));
        }
    }
   
    /**
     * Erweitert die BoundingBox um einen Punkt.
     *
     * @param punkt  Der einzuschlie�ende Punkt.
     */
    private void erweitereBoundingBox(final Vektor2D punkt) {
        if (punkt.x < this.boundingBox.liObEcke().x) {
            this.boundingBox.setLinks(punkt.x);
        } else if (punkt.x > this.boundingBox.getRechtUntEcke().x) {
            this.boundingBox.setRechts(punkt.x);
        }
       
        if (punkt.y < this.boundingBox.liObEcke().y) {
            this.boundingBox.setOben(punkt.y);
        } else if (punkt.y > this.boundingBox.getRechtUntEcke().y) {
            this.boundingBox.setUnten(punkt.y);
        }
    }

    /**
     * Ung�ltige Funktion auf Polygonen.
     *
     * @param c  Kollektion.
     *
     * @return  Ob ge�ndert.
     */
    @Override
    public boolean addAll(final Collection< ? extends Vektor2D> c) {
        throw new RuntimeException("Funktion nicht unterst�tzt f�r Polygone");
    }

    /**
     * Ung�ltige Funktion auf Polygonen.
     *
     * @param c      Kollektion.
     * @param index  Index.
     *
     * @return  Ob ge�ndert.
     */
    @Override
    public boolean addAll(final int index,
            final Collection< ? extends Vektor2D> c) {
        throw new RuntimeException("Funktion nicht unterst�tzt f�r Polygone");
    }

    /**
     * L�scht alle Punkte des Polygons.
     */
    @Override
    public void clear() {
        super.clear();
        this.boundingBox = null;
        this.xPoints.clear();
        this.yPoints.clear();
    }

    /**
     * L�scht den Punkt mit der angegebenen Nummer. Vorsicht, sollte nicht
     * h�ufig alternierend mit add-Operationen eingesetzt werden, da nach
     * remove beim n�chsten add die boundingBox neu berechnet werden muss.
     *
     * @param index  Die Nummer.
     *
     * @return  Das entfernte Element.
     */
    @Override
    public Vektor2D remove(final int index) {
        this.xPoints.remove(index);
        this.yPoints.remove(index);
        this.boundingBox = null;
        return super.remove(index);
    }
   
    /**
     * Verschiebt das Polygon um den angegebenen Vektor.
     *
     * @param vek  Der Verschiebevektor.
     */
    public void verschiebe(final Vektor2D vek) {
        for (Vektor2D pVek : this) {
            pVek.add(vek);
        }
       
        if (this.boundingBox != null) {
            this.boundingBox.verschiebe(vek);
        }
    }
   
    /**
     * Skaliert das Polygon um die angegebene X- und Y-Richtung und den
     * angegebenen Mittelpunkt.
     *
     * @param skal   Der Skalierungsvektor.
     * @param mitte  Der Mittelpunkt des Skalierens.
     */
    public void skaliere(final Vektor2D mitte, final Vektor2D skal) {
        for (Vektor2D pVek : this) {
            pVek.skaliere(mitte, skal);
        }
    }
   
    /**
     * Dreht das Polygon um den angegebenen Winkel und den angegebenen
     * Mittelpunkt.
     *
     * @param mitte   Der Mittelpunkt.
     * @param winkel  Der Drehwinkel.
     */
    public void drehe(final Vektor2D mitte, final double winkel) {
        for (Vektor2D pVek : this) {
            pVek.drehe(mitte, winkel);
        }
    }
   
    /**
     * Ung�ltige Funktion auf Polygonen.
     *
     * @param o  Objekt.
     *
     * @return  Ob ge�ndert.
     */
    @Override
    public boolean remove(final Object o) {
        throw new RuntimeException("Funktion nicht unterst�tzt f�r Polygone");
    }

    /**
     * L�scht Objekte in einem Bereich.
     *
     * @param fromIndex  Von.
     * @param toIndex    Bis.
     */
    @Override
    protected void removeRange(final int fromIndex, final int toIndex) {
        for (int i = fromIndex; i < toIndex; i++) {
            this.remove(fromIndex);
        }
    }

    /**
     * Setzt einen Punkt neu. Vorsicht, ineffizient; sollte nur zu Testzwecken
     * oder aus Bequemlichkeit, wenn Zeit keine Rolle spielt, eingesetzt
     * werden (siehe auch Kommentar zu remove).
     *
     * @param index    Der neu zu setzende Index.
     * @param element  Das neue Element.
     *
     * @return  Das Element, das vorher an der Position war. Wenn das Element
     *          nicht gesetzt werden konnte, wird <code>null</code>
     *          zur�ckgegeben.
     */
    @Override
    public Vektor2D set(final int index, final Vektor2D element) {
        Vektor2D alt = this.get(index);
       
        this.remove(index);
        this.add(index, element);
       
        if (this.garantiereEinfach) {
            if (!this.isEinfach()) {
                this.remove(index);
                this.add(index, alt);
                return null;
            }
        }
       
        return alt;
    }

    /**
     * @return Returns the xPoints.
     */
    public ArrayList<Double> xPoints() {
        return this.xPoints;
    }

    /**
     * @return Returns the yPoints.
     */
    public ArrayList<Double> yPoints() {
        return this.yPoints;
    }
   
    /**
     * @return  Die Anzahl der Punkte.
     */
    public int nPoints() {
        return this.size();
    }

    /**
     * @return  Die BoundingBox.
     */
    public Rechteck2D getBoundingBox() {
        if (this.boundingBox == null) {
            this.createBoundingBox();
        }
        return this.boundingBox;
    }

    /**
     * Erzeugt ein Java-Polygon aus <code>this</code> ohne zu skalieren oder
     * zu verschieben.
     *
     * @return  Polygon.
     */
    public Polygon toPol() {
        return this.toPol(1, Vektor2D.NULL_VEKTOR);
    }

    /**
     * Erzeugt ein Java-Polygon aus <code>this</code>.
     *
     * @param skalierung  Die Skalierung des Polygons.
     * @param versch      Die Verschiebung des Polygons NACH der Skalierung.
     *
     * @return  Polygon.
     */
    public Polygon toPol(final double skalierung, final Vektor2D versch) {
        Polygon pol = new Polygon();
        Iterator<Vektor2D> it = this.iterator();
        Vektor2D punkt;
       
        while (it.hasNext()) {
            punkt = it.next();
            pol.addPoint((int) (punkt.x * skalierung + versch.x),
                         (int) (punkt.y * skalierung + versch.y));
        }
       
        return pol;
    }

    /**
     * Normalisiert das aktuelle Objekt, so dass der Abstand
     * zwischen zwei in der Liste benachbarten Punkten immer dem
     * Durchschnittsabstand der Punkte in der urspr�nglichen Liste entspricht,
     * wobei der Kurvenverlauf "m�glichst nah" am Verlauf der urspr�nglichen
     * Kurve liegt.
     */
    public void normalisiere2() {
        Polygon2D normArr = new Polygon2D(this.nPoints());
        ArrayList<Double> abstaende = new ArrayList<Double>(this.nPoints());
        Iterator<Vektor2D> it = this.iterator();
        Vektor2D letztV;
        Vektor2D aktV = new Vektor2D(Vektor2D.NULL_VEKTOR);
        double aktAbst;
        double letztAbst;
        Vektor2D aktRicht;
        double durchAbst;
        int i = 0;

        if (this.nPoints() <= 2) {
            return;
        }
       
        letztV = this.get(0);
        letztAbst = 0;
        while (it.hasNext()) {
            aktV = it.next();
           
            aktAbst = aktV.distanz(letztV) + letztAbst;
            abstaende.add(aktAbst);
           
            letztAbst = aktAbst;
            letztV = aktV;
        }

        durchAbst = abstaende.get(abstaende.size() - 1)
                    / (abstaende.size() - 1);
       
        aktV = new Vektor2D(this.get(0));
        normArr.add(aktV);
        aktAbst = 0;
        while (i < this.nPoints()) {
            if (i + 1 < this.nPoints()) {
                aktRicht = new Vektor2D(this.get(i + 1));
                aktRicht.sub(this.get(i));
               
                if (this.get(i).distanz(this.get(i + 1)) >= durchAbst) {
                    aktRicht.laengeFestlegen(durchAbst);
                   
                    while (aktAbst < abstaende.get(i + 1)) {
                        aktV = new Vektor2D(aktV);
                        aktV.add(aktRicht);
                        normArr.add(aktV);
                        aktAbst += durchAbst;
                    }
                } else {
                    double zwischAbst = 0;
                    double aktDist;
                   
                    while (i + 1 < nPoints()) {
                        aktDist = this.get(i).distanz(this.get(i + 1));
                       
                        if (zwischAbst + aktDist
                                < durchAbst) {
                            zwischAbst += aktDist;
                            i++;
                        } else {
                            aktRicht = new Vektor2D(this.get(i + 1));
                            aktRicht.sub(this.get(i));
                            aktRicht.laengeFestlegen(durchAbst - zwischAbst);
                            aktV = new Vektor2D(this.get(i));
                            aktV.add(aktRicht);
                            normArr.add(aktV);
                            aktAbst += durchAbst;
                            break;
                        }
                    }
                }
            }
           
            i++;
        }
       
        this.clear();
        for (int j = 0; j < normArr.size(); j++) {
            this.add(normArr.get(j));
        }
    }

    /**
     * Normalisiert das aktuelle Objekt, so dass der Abstand
     * zwischen zwei in der Liste benachbarten Punkten immer dem
     * Durchschnittsabstand der Punkte in der urspr�nglichen Liste entspricht,
     * wobei der Kurvenverlauf "m�glichst nah" am Verlauf der urspr�nglichen
     * Kurve liegt. Dabei kann die Anzahl der Punkte sich um 1 erh�hen.
     *
     * @return  Die normalisierte Liste.
     */
    public Polygon2D normalisiere() {
        Polygon2D normArr = new Polygon2D(this.nPoints());
        ArrayList<Double> abstaende = new ArrayList<Double>(this.nPoints());
        Iterator<Vektor2D> it = this.iterator();
        Vektor2D letztV;
        Vektor2D aktV = new Vektor2D(Vektor2D.NULL_VEKTOR);
        double aktAbst;
        double letztAbst;
        Vektor2D aktRicht;
        double durchAbst;
        int i = 0;
       
        if (this.nPoints() <= 1) {
            return this;
        }
       
        letztV = this.get(0);
        letztAbst = 0;
        while (it.hasNext()) {
            aktV = it.next();
           
            aktAbst = aktV.distanz(letztV) + letztAbst;
            abstaende.add(aktAbst);
           
            letztAbst = aktAbst;
            letztV = aktV;
        }

        durchAbst = abstaende.get(abstaende.size() - 1)
                    / (abstaende.size() - 1);
       
        aktV = new Vektor2D(this.get(0));
        normArr.add(aktV);
        aktAbst = 0;
        while (i < this.nPoints()) {
            if (i + 1 < this.nPoints()) {
                aktRicht = new Vektor2D(this.get(i + 1));
                aktRicht.sub(this.get(i));
                aktRicht.laengeFestlegen(durchAbst);
               
                while (aktAbst < abstaende.get(i + 1)) {
                    aktV = new Vektor2D(aktV);
                    aktV.add(aktRicht);
                    normArr.add(aktV);
                    aktAbst += durchAbst;
                }
            }
           
            i++;
        }

        if (normArr.size() - this.nPoints() != 1
                && normArr.size() - this.nPoints() != 0) {
            throw new RuntimeException(
                    "Normalisierung lieferte zu viele / wenige Punkte: "
                    + normArr.size() + " vs. " + this.nPoints());
        }

        return normArr;
    }

    /**
     * Berechnet, ob der �bergebene Punkt sich innerhalb der Grenzen des
     * Polygons befindet.
     *
     * @param punkt  Der Punkt, dessen Eigenschaft �berpr�ft werden soll.
     *
     * @return       Ob der Punkt innerhalb des Polygons liegt.
     */
    public boolean istPunktInnen(final Vektor2D punkt) {
        boolean inside = false;
        double x1 = this.xPoints.get(this.nPoints() - 1);
        double y1 = this.yPoints.get(this.nPoints() - 1);
        double x2 = this.xPoints().get(0);
        double y2 = this.yPoints().get(0);
        boolean startUeber;
        boolean endeUeber;
       
        if (y1 >= punkt.y) {
            startUeber = true;
        } else {
            startUeber = false;
        }
       
        for (int i = 1; i <= this.nPoints(); i++) {
            if (y2 >= punkt.y) {
                endeUeber = true;
            } else {
                endeUeber = false;
            }
         
            if (startUeber != endeUeber) {
                if ((y2 - punkt.y) * (x2 - x1) <= (y2 - y1) * (x2 - punkt.x)) {
                    if (endeUeber) {
                        inside = !inside;
                    }
                } else {
                    if (!endeUeber) {
                        inside = !inside;
                    }
                }
            }

            startUeber = endeUeber;
            y1 = y2;
            x1 = x2;
            if (i < this.nPoints()) {
                x2 = this.xPoints.get(i);
                y2 = this.yPoints.get(i);
            }
        }
       
        return inside;
    }
   
    /**
     * @return  Eine einfache Variante von <code>this</code>.
     */
    public Polygon2D toEinfach() {
        Polygon2D neu = new Polygon2D(this.nPoints());
        Vektor2D akt;
        Iterator<Vektor2D> it = this.iterator();
        neu.erzwingeEinfach(true);
       
        while (it.hasNext()) {
            akt = it.next();
            neu.add(akt);
        }
       
        return neu;
    }

    /**
     * @return  Ob das Polygon einfach ist.
     */
    public boolean isEinfach() {
        // TODO:
        return false;
    }

    /**
     * Wenn Einfachheit erzwungen wird, dann wird gepr�ft, ob die beiden
     * neuen Strecken, die zum Polygon durch den Punkt hinzukommen w�rden,
     * das Polygon schneiden und in diesem Fall der Punkt ignoriert.
     *
     * Zu beachten ist, dass das Polygon in jedem Aufbauschritt einfach
     * bleiben muss und es nicht m�glich ist, ein zwischenzeitlich komplexes
     * Polygon zu erzeugen und nachtr�glich einfach zu machen.
     *
     * @param setzen The garantiereEinfach to set.
     *
     * @return  Ob Einfachheit erzwungen werden konnte.
     */
    public boolean erzwingeEinfach(final boolean setzen) {
        this.garantiereEinfach = setzen;

        if (this.nPoints() > 0 && !this.isEinfach()) {
            this.garantiereEinfach = false;
        }
       
        return this.garantiereEinfach;
    }

    /**
     * @param params The pars to set.
     */
    public void setPars(final Parametersatz params) {
        this.pars = params;
    }
   
    /**
     * @return  Mittelpunkt des Polygons.
     */
    public Vektor2D mittelpunkt() {
        return new Vektor2D(
                this.getBoundingBox().liObEcke().x
                    + this.getBoundingBox().getBreite() / 2,
                this.getBoundingBox().liObEcke().y
                    + this.getBoundingBox().getHoehe() / 2);
    }
   
    /**
     * Gibt die Position des (ersten) Vektors zur�ck, der genau dem
     * �bergebenen Objekt entspricht.
     *
     * @param vek  Der zu vergleichende Vektor.
     *
     * @return  Die (erste) Position des Vektors. Falls nicht vorhanden: -1.
     */
    public int realIndexOf(final Vektor2D vek) {
        for (int i = 0; i < this.size(); i++) {
            if (this.get(i) == vek) {
                return i;
            }
        }
       
        return -1;
    }
}
TOP

Related Classes of fmg.fmg8.graphVis.zeichenModi.Polygon2D

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.