Package fmg.fmg8.graphVis.zeichenModi

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

/*
* Datei: ZeichenModusEA.java
* Autor(en):        Lukas K�nig
* Java-Version:     6.0
* Erstellt (vor):   24.11.2008
*
* (c) Lukas K�nig, die Datei unterliegt der LGPL
* -> http://www.gnu.de/lgpl-ger.html
*/

package fmg.fmg8.graphVis.zeichenModi;

import fmg.fmg8.graphVis.DargestellterGraph;
import fmg.fmg8.graphVis.graph.Knoten;
import fmg.fmg8.sonstiges.SonstMeth;
import fmg.fmg8.statistik.Parametersatz;
import fmg.fmg8.umgebung2D.Vektor2D;

import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Point;
import java.awt.Polygon;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
* Klasse zum Erzeugen von geometrischen Figuren in Pfeilform.
* <P>
* Wenn eine Objektliste zur�ckgegeben wird, enth�lt diese Polygone,
* die fertig gezeichnet werden k�nnen und folgenderma�en codierte Strings:
* Drei aufeinanderfolgende Listenelemente bezeichnen:
* 1. Als Integer-Objekt die x-Koordinate,
* 2. Als Integer-Objekt die y-Koordinate und
* 3. Als String-Objekt den auszugebenden Text.
* z. B. liste = Pol, Pol, X-Koor, Y-Koor, String, Pol, ...
*                         ^^^^^^^^^^^^^^^^^^^^^^
*                         |---String-Objekt----|
*
* @author Lukas K�nig
*/
public class PfeilMaster implements Serializable {

    /**
     * Die Serial Version ID (generiert am 25. April 2007).
     */
    private static final long serialVersionUID = -4051109731656095692L;

    /**
     * Gibt an, wie lang die Pfeilspitze (absolut) ist.
     */
    private double pfeilSpLaenge;

    /**
     * Gibt die Pfeildicke absolut in Pixeln an.
     */
    private int pfeilDicke;

    /**
     * Der aktuelle darzustellende Graph.
     */
    private DargestellterGraph aktGraph;

    /**
     * Durchmesser von Knoten.
     */
    private double knotenDurchm;

    /**
     * Liste der bereits in einer Richtung dargestellten Doppelkanten.
     */
    private ArrayList<Polygon> dopp;

    /**
     * Speichert die Zuordnung der Kanten im Graphen...
     */
    private ArrayList<Polygon> urspKanten;

    /**
     * ...zu den tats�chlich berechneten Ursprungs- und Ziel-Koordinaten.
     */
    private ArrayList<Polygon> echteKant;

    /**
     * Parameter.
     */
    private Parametersatz pars;
   
    /**
     * Einfacher Abschluss, also ohne Spitze.
     */
    public static final Polygon2D EINFACHER_ABSCHLUSS
          = PfeilMaster.erzeugeKonstanteEnden(0);
   
    /**
     * Einfache Spitze.
     */
    public static final Polygon2D EINFACHE_SPITZE_1
          = PfeilMaster.erzeugeKonstanteEnden(1);

    /**
     * Einfache Spitze.
     */
    public static final Polygon2D EINFACHE_SPITZE_2
          = PfeilMaster.erzeugeKonstanteEnden(4);

    /**
     * Einfache Spitze.
     */
    public static final Polygon2D EINFACHE_SPITZE_3
          = PfeilMaster.erzeugeKonstanteEnden(5);

    /**
     * Doppelspitzes Ende.
     */
    public static final Polygon2D DOPPELSPITZES_ENDE
          = PfeilMaster.erzeugeKonstanteEnden(2);

    /**
     * Kugeliges Ende.
     */
    public static final Polygon2D KUGEL_ENDE
          = PfeilMaster.erzeugeKonstanteEnden(3);

    /**
     * Kugeliges Ende.
     */
    public static final Polygon2D RUECK_PFEIL
          = PfeilMaster.erzeugeKonstanteEnden(6);

    /**
     * Erzeugt einige vordefinierte Endentypen.
     * 0 = Gerades Ende.
     * 1 = Normale Pfeilspitze 1.
     * 2 = Doppelspitzes Ende.
     * 3 = Kugel-Ende.
     * 4 = Normale Pfeilspitze 2.
     * 5 = Normale Pfeilspitze 3.
     * 6 = R�ckbez�gliche Pfeilspitze.
     *
     * @param nummer  Die Nummer des Endentyps.
     *
     * @return  Eine Liste mit Punkten, die diesen Endentyp beschreiben.
     */
    private static Polygon2D erzeugeKonstanteEnden(final int nummer) {
        Vektor2D v;
        Polygon2D a = null;
       
        if (nummer == 0) {
            a = new Polygon2D(0);
        }

        if (nummer == 1) {
            a = new Polygon2D(3);
            v = new Vektor2D(1.8, -0.7);
            a.add(v);
            v = new Vektor2D(0, 5);
            a.add(v);
            v = new Vektor2D(-1.8, -0.7);
            a.add(v);
        }

        if (nummer == 2) {
            a = new Polygon2D(1);
            v = new Vektor2D(Vektor2D.NULL_VEKTOR);
            v.sub(new Vektor2D(0, 0.3));
            a.add(v);
        }

        if (nummer == 3) {
            a = fmg.fmg8.graphVis.zeichenModi.Geometrie2D.bezierKurve(
                    new Vektor2D(0.5, 0),
                    new Vektor2D(5, 5),
                    new Vektor2D(-5, 5),
                    new Vektor2D(-0.5, 0),
                    0.0001);
        }
       
        if (nummer == 4) {
            a = new Polygon2D(3);
            v = new Vektor2D(1.8, 0);
            a.add(v);
            v = new Vektor2D(0, 7);
            a.add(v);
            v = new Vektor2D(-1.8, 0);
            a.add(v);
        }
       
        if (nummer == 5) {
            a = new Polygon2D(6);
            v = new Vektor2D(2.3, -1.7);
            a.add(v);
            v = new Vektor2D(2.85, -1.7);
            a.add(v);
            v = new Vektor2D(0, 1.1);
            a.add(v);
            v = new Vektor2D(-2.85, -1.7);
            a.add(v);
            v = new Vektor2D(-2.3, -1.7);
            a.add(v);
        }

        if (nummer == 6) {
            Parametersatz params = new Parametersatz(new String[0]);
            params.ergaenze();
            PfeilMaster zeichnen = new PfeilMaster(params);

            ArrayList<Double> dicken = new ArrayList<Double>();
            Polygon2D bez = new Polygon2D();

            for (double i = 0.5 * Math.PI; i <= Math.PI * 1.5; i += 0.001) {
                bez.add(new Vektor2D(
                        -(Math.sin(i) * 4 - Math.sin(0.5 * Math.PI) * 4),
                        -(Math.cos(i) * 4 - Math.cos(0.5 * Math.PI) * 4)));
            }
           
            for (double i = 0; i < bez.size(); i += 1) {
                dicken.add(1.0);
            }

            a = zeichnen.segmentPfeilPol2D(
                    bez,
                    dicken,
                    PfeilMaster.EINFACHER_ABSCHLUSS,
                    PfeilMaster.EINFACHE_SPITZE_1,
                    new Vektor2D(1, 1),
                    new Vektor2D(0.75, 0.75));
        }

        return a;
    }
   
    /**
     * Konstruktor, der alle Attribute mit den als Parameter �bergebenen
     * Werten initialisiert.
     *
     * @param pfD       Pfeildicke (absolut in Pixeln).
     * @param pfSpL     Pfeilspitzenl�nge (absolut in Pixeln).
     * @param stDicke   Dicke der zur Pfeilrichtung senkrechten SkalenStriche.
     * @param stLaenge  L�nge der zur Pfeilrichtung senkrechten Skalenstriche.
     * @param knDurchm  Durchmesser von Knoten.
     * @param par       Die Parameter.
     */
    public PfeilMaster(final int    pfD,
                       final double pfSpL,
                       final double stDicke,
                       final double stLaenge,
                       final double knDurchm,
                       final Parametersatz par) {
        this.pfeilDicke    = pfD;
        this.pfeilSpLaenge = pfSpL;
        this.knotenDurchm  = knDurchm;
        this.aktGraph      = null;
        this.dopp          = new ArrayList<Polygon>();
        this.urspKanten    = new ArrayList<Polygon>();
        this.echteKant     = new ArrayList<Polygon>();
        this.pars          = par;
    }

    /**
     * Konstruktor, der alle Attribute mit den Werten aus der Klasse
     * Konstanten initialisiert.
     *
     * @param par  Die Parameter.
     */
    public PfeilMaster(final Parametersatz par) {
        this(Konstanten.PFEIL_DICKE,
             Konstanten.PFEILSP_LAENGE,
             Konstanten.STRICH_DICKE,
             Konstanten.STRICH_LAENGE,
             Konstanten.KN_DURCHM,
             par);
    }

    /**
     * Gibt die Eckpunkte eines Polygons zur�ck, das einen Pfeil von
     * P1 (x1, y1) nach P2 (x2, y2) darstellt (in eine Richtung).
     *
     * @param xx1  X-Koordinate des Startpunkts des Pfeils.
     * @param xx2  X-Koordinate des Endpunkts des Pfeils.
     * @param yy1  Y-Koordinate des Startpunkts des Pfeils.
     * @param yy2  Y-Koordinate des Endpunkts des Pfeils.
     * @param staerke    Die St�rke des Pfeils.
     * @param gebogen  Ob der Pfeil gebogen sein darf.
     *
     * @return  Polygon in Gestalt eines Pfeils.
     */
    public Polygon pfeilEinfach(final int xx1,
                                final int yy1,
                                final int xx2,
                                final int yy2,
                                final double staerke,
                                final boolean gebogen) {
        return this.bezierPfeil(xx1, yy1, xx2, yy2, staerke, gebogen);
    }

    /**
     * Gibt die Eckpunkte eines Polygons zur�ck, das einen Pfeil von
     * P1 (x1, y1) nach P2 (x2, y2) darstellt (in eine Richtung).
     *
     * @param xx1        X-Koordinate des Startpunkts des Pfeils.
     * @param yy1        Y-Koordinate des Startpunkts des Pfeils.
     * @param xx2        X-Koordinate des Endpunkts des Pfeils.
     * @param yy2        Y-Koordinate des Endpunkts des Pfeils.
     * @param staerke    Die St�rke des Pfeils.
     * @param gebogen    Ob der Pfeil gebogen sein soll.
     *
     * @return  Polygon in Gestalt eines Pfeils.
     */
    public Polygon bezierPfeil(
            final int xx1,
            final int yy1,
            final int xx2,
            final int yy2,
            final double staerke,
            final boolean gebogen) {
        int x1 = xx1;
        int y1 = yy1;
        int x2 = xx2;
        int y2 = yy2;
        double letztX;
        double letztY;
        Polygon dieseKante;
        int konstVersch = (int) ((double) Konstanten.PFEIL_DICKE * 2.3);
        double vektorLen;
        double x1d;
        double x2d;
        double y1d;
        double y2d;
        Polygon2D bez;
        ArrayList<Double> dick;
       
        Vektor2D pk0, pk1, pk2, pk3;
       
        if (!gebogen) {
            Vektor2D p1 = new Vektor2D(xx1, yy1);
            Vektor2D p2 = new Vektor2D(xx2, yy2);
            Polygon2D a = new Polygon2D(2);
            a.add(p1);
            a.add(p2);
            dick = new ArrayList<Double>(2);
            dick.add(staerke * Konstanten.DICKEN_REG_ST 
                             + this.pfeilDicke);
            dick.add((double) this.pfeilDicke);
           
            return this.segmentPfeilPol(a,
                                     dick,
                                     DOPPELSPITZES_ENDE,
                                     EINFACHE_SPITZE_1,
                                     new Vektor2D(1, 1),
                                     new Vektor2D(1, 1),
                                     1,
                                     Vektor2D.NULL_VEKTOR);
        }
       
        if (x1 == x2 && y1 == y2) {
            letztX = x1 + Konstanten.KN_DURCHM / 2;
            letztY = y1 + Konstanten.KN_DURCHM / 2;
           
            pk0 = new Vektor2D(letztX,
                             letztY);
            pk1 = new Vektor2D(letztX + 80,
                             letztY + 40);
            pk2 = new Vektor2D(letztX + 80,
                             y1 - Konstanten.KN_DURCHM / 2
                                  + this.pfeilDicke / 2 - 30);
            pk3 = new Vektor2D(letztX + this.pfeilSpLaenge - 2,
                             y1 - Konstanten.KN_DURCHM / 2
                                + this.pfeilDicke / 2 - 9);
           
            bez = fmg.fmg8.graphVis.zeichenModi.Geometrie2D.bezierKurve(
                    pk0,
                    pk1,
                    pk2,
                    pk3,
                    this.pars.getBezier());
           
            if (this.pars.getEinfacheDar()) {
                dick = null;
            } else {
                dick = new ArrayList<Double>(bez.size());
                for (double i = 0; i <= bez.size(); i++) {
                    dick.add((bez.size() - i) * staerke / bez.size()
                            * Konstanten.DICKEN_REG_ST 
                             + this.pfeilDicke);
                }
            }
           
            return this.segmentPfeilPol(bez,
                                     dick,
                                     DOPPELSPITZES_ENDE,
                                     EINFACHE_SPITZE_1,
                                     new Vektor2D(1, 1),
                                     new Vektor2D(1, 1),
                                     1,
                                     Vektor2D.NULL_VEKTOR);
           
        } else {
            Vektor2D vv = new Vektor2D(x2, y2);
            vv.sub(new Vektor2D(x1, y1));
            vv.normal();
            vv.mult(35);
           
            x1 += vv.x;
            y1 += vv.y;
            x2 -= vv.x;
            y2 -= vv.y;

            // Die aktuelle Kante ist eine Doppelkante.
            if (this.aktGraph.enthaeltPfeil(xx2, yy2, xx1, yy1)) {
                x1d = (double) x1;
                x2d = (double) x2;
                y1d = (double) y1;
                y2d = (double) y2;
                vektorLen = Math.sqrt(Math.pow(x2d - x1d, 2)
                                    + Math.pow(y1d - y2d, 2));

                dieseKante = new Polygon();
                dieseKante.addPoint(x1, y1);
                dieseKante.addPoint(x2, y2);

                if (this.dopp.contains(dieseKante)) {
                    x1d = x1d + ((y1d - y2d) / vektorLen) * konstVersch;
                    x2d = x2d + ((y1d - y2d) / vektorLen) * konstVersch;
                    y1d = y1d + ((x2d - x1d) / vektorLen) * konstVersch;
                    y2d = y2d + ((x2d - x1d) / vektorLen) * konstVersch;
                } else {
                    x1d = x1d - ((y1d - y2d) / vektorLen) * konstVersch;
                    x2d = x2d - ((y1d - y2d) / vektorLen) * konstVersch;
                    y1d = y1d - ((x2d - x1d) / vektorLen) * konstVersch;
                    y2d = y2d - ((x2d - x1d) / vektorLen) * konstVersch;
                    this.dopp.add(dieseKante);
                }
                x1 = (int) x1d;
                x2 = (int) x2d;
                y1 = (int) y1d;
                y2 = (int) y2d;
            } else {
                Vektor2D v0 = new Vektor2D(x2, y2);
                v0.sub(new Vektor2D(x1, y1));
                v0.ortho();
                v0.normal();
                v0.mult(12);
               
                x1 += v0.x;
                x2 += v0.x;
                y1 += v0.y;
                y2 += v0.y;
            }

            Polygon pol1 = new Polygon();
            Polygon pol2 = new Polygon();

            pol1.addPoint(xx1, yy1);
            pol1.addPoint(xx2, yy2);
            pol2.addPoint(x1, y1);
            pol2.addPoint(x2, y2);

            this.urspKanten.add(pol1);
            this.echteKant.add(pol2);

            Vektor2D v = new Vektor2D(x2, y2);
            double dist = new Vektor2D(x1, y1).distanz(new Vektor2D(x2, y2));
           
            v.sub(new Vektor2D(x1, y1));
            v.normal();
            v.mult(this.pfeilSpLaenge);
            Vektor2D v1 = new Vektor2D(x1, y1);
            Vektor2D v2 = new Vektor2D(x2, y2);
            v2.sub(v);
           
            Vektor2D n1 = new Vektor2D((x1 + x2) / 2, (y1 + y2) / 2);
            Vektor2D n2 = new Vektor2D((x1 + x2) / 2, (y1 + y2) / 2);
            v.ortho();
            v.normal();
            Vektor2D zwisch = new Vektor2D(x2, y2);
            zwisch.sub(new Vektor2D(x1, y2));
           
            v.mult(Math.sqrt(Math.max(dist - 100, 0)) + 0.1);
           
           
            n1.add(v);
            n2.add(v);
           
            bez = fmg.fmg8.graphVis.zeichenModi.Geometrie2D.bezierKurve(
                    v1,
                    n1,
                    n2,
                    v2,
                    this.pars.getBezier());
            if (this.pars.getEinfacheDar()) {
                dick = null;
            } else {
                dick = new ArrayList<Double>(bez.size());
                for (double i = 0; i <= bez.size(); i++) {
                    dick.add((bez.size() - i) * staerke / bez.size()
                            * Konstanten.DICKEN_REG_ST
                             + this.pfeilDicke);
                }
            }

            return this.segmentPfeilPol(bez,
                                     dick,
                                     DOPPELSPITZES_ENDE,
                                     EINFACHE_SPITZE_1,
                                     new Vektor2D(1, 1),
                                     new Vektor2D(1, 1),
                                     1,
                                     Vektor2D.NULL_VEKTOR);
        }
    }
   
    /**
     * Gibt einen einfachen Knoten als quadratisches Polygon zur�ck.
     *
     * @param x  X-Koordinate des Knotens.
     * @param y  Y-Koordinate des Knotens.
     *
     * @return  Polygon, das den Knoten repr�sentiert.
     */
    public Polygon knotenEinfach(final int x, final int y) {
        final Polygon quadrat = new Polygon();
        double        xQ;
        double        yQ;

        xQ = x - this.knotenDurchm / 2.0;
        yQ = y - this.knotenDurchm / 2.0;
        quadrat.addPoint((int) xQ, (int) yQ);

        xQ = x - this.knotenDurchm / 2.0;
        yQ = y + this.knotenDurchm / 2.0;
        quadrat.addPoint((int) xQ, (int) yQ);

        xQ = x + this.knotenDurchm / 2.0;
        yQ = y + this.knotenDurchm / 2.0;
        quadrat.addPoint((int) xQ, (int) yQ);

        xQ = x + this.knotenDurchm / 2.0;
        yQ = y - this.knotenDurchm / 2.0;
        quadrat.addPoint((int) xQ, (int) yQ);

        return fmg.fmg8.graphVis.zeichenModi.Geometrie2D.kreis(
                new Vektor2D(x, y),
                31,
                (int) (1 / this.pars.getBezier()));
    }

    /**
     * Gibt einen Graphen als Liste von Polygon-Objekten zur�ck,
     * die mit Java.Awt direkt gezeichnet werden k�nnen. Beschriftungen werden
     * nicht gezeichnet.
     *
     * @param g  Zu zeichnender Graph.
     *
     * @return  Liste von zu zeichnenden Objekten.
     */
    public List<Object> graph(final DargestellterGraph g) {
        final ArrayList<Object> polygonListe = new ArrayList<Object>();
        final ArrayList<Point> knotenKoord  = g.holeKnotenKoord();
        final ArrayList<Double> pfeilStaerken  = g.holePfeilStaerken();
        final ArrayList<Knoten> knotenObj    = g.holeKnotenObj();
        final ArrayList<Point> pfeilUrsp    = g.holePfeilUrspr();
        final ArrayList<Point> pfeilEnpk    = g.holePfeilEnd();
        final ArrayList<String> beschr       = g.holeBeschr();
        final ArrayList<Point> beschrKoord  = g.holeBeschrKoord();
        final ArrayList<Boolean> pfeilGebogen = g.holePfeilBiegung();
        Polygon               aktuellesPol;
        String                aktBeschr;
        Point                 aktPunktU;
        Point                 aktPunktE;
        Point                 aktPunktK;
        Point                 aktPunktB;
        final Iterator<Point> itU;
        final Iterator<Point> itE;
        final Iterator<Double> itS;
        final Iterator<Point> itK;
        final Iterator<Knoten> itKO2;
        final Iterator<Boolean> itG;
        final Iterator<String> itB;
        final Iterator<Point> itBK;
        final AusgMerkm ausgPfeile;
        AusgMerkm       ausgKnoten;
        Color                 knotenFarbe;
        Object                aktKnot;

        this.aktGraph = g;

        if (this.pars.getEinfacheDar()) {
            ausgPfeile = new AusgMerkm(Color.BLACK,
                                             Color.LIGHT_GRAY,
                                             true,
                                             true,
                                             "Calibri",
                                             Font.PLAIN,
                                             14);
        } else {
            ausgPfeile = new AusgMerkm(Color.BLACK,
                                             Color.ORANGE,
                                             true,
                                             true,
                                             "Calibri",
                                             Font.PLAIN,
                                             14);
        }

        itU = pfeilUrsp.iterator();
        itE = pfeilEnpk.iterator();
        itS = pfeilStaerken.iterator();
        itG = pfeilGebogen.iterator();
        polygonListe.add(ausgPfeile);
        while (itU.hasNext() && itE.hasNext() && itS.hasNext()) {
            aktPunktU = itU.next();
            aktPunktE = itE.next();
            aktuellesPol = this.pfeilEinfach(aktPunktU.x,
                                             aktPunktU.y,
                                             aktPunktE.x,
                                             aktPunktE.y,
                                             itS.next(),
                                             itG.next());
            polygonListe.add(aktuellesPol);
        }

        itK = knotenKoord.iterator();
        itKO2 = knotenObj.iterator();
        while (itK.hasNext() && itKO2.hasNext()) {
            aktKnot = itKO2.next();
            aktPunktK = itK.next();
            if (g.getSelektiert(aktKnot)) {
                if (this.pars.getEinfacheDar()) {
                    knotenFarbe = Color.LIGHT_GRAY;
                } else {
                    knotenFarbe = Konstanten.MARKIERT_FUELL_FARBE;
                }
            } else {
                if (this.pars.getEinfacheDar()) {
                    knotenFarbe = Color.white;
                } else {
                    knotenFarbe = Konstanten.STANDARD_FUELL_FARBE;
                }
            }
            ausgKnoten = new AusgMerkm(Color.BLACK,
                                             knotenFarbe,
                                             true,
                                             true,
                                             "Calibri",
                                             Font.PLAIN,
                                             14);
            aktuellesPol = this.knotenEinfach(aktPunktK.x, aktPunktK.y);
            polygonListe.add(ausgKnoten);
            polygonListe.add(aktuellesPol);
        }

        itB  = beschr.iterator();
        itBK = beschrKoord.iterator();
        while (itB.hasNext() && itBK.hasNext()) {
            int x;
            int y;
            Polygon pol;
            Polygon ass;
            int x1;
            int x2;
            int y1;
            int y2;
            int x1ass;
            int x2ass;
            int y1ass;
            int y2ass;
            aktPunktB = itBK.next();
            aktBeschr = itB.next();
            String nBeschr;
            int nBInt;

            x = aktPunktB.x;
            y = aktPunktB.y;

            ass = (Polygon) g.holeAssoz(aktBeschr);
            if (ass != null && ass.npoints == 0) {
                int trennInd = 0;
                while (aktBeschr.charAt(trennInd) != '-') {
                    trennInd++;
                }
                nBInt = Integer.parseInt(aktBeschr.substring(0, trennInd));
                nBeschr = aktBeschr.substring(trennInd);
                aktBeschr = fmg.fmg8.umgebung2D.Konstanten.BEF[nBInt] + nBeschr;
                ass = null;
            }
            if (ass != null) {
                int i = 0;
                x1ass = ass.xpoints[0];
                x2ass = ass.xpoints[1];
                y1ass = ass.ypoints[0];
                y2ass = ass.ypoints[1];
                while (i < this.urspKanten.size()) {
                    pol = (Polygon) this.urspKanten.get(i);
                    x1 = pol.xpoints[0];
                    x2 = pol.xpoints[1];
                    y1 = pol.ypoints[0];
                    y2 = pol.ypoints[1];

                    if (x1ass == x1 && x2ass == x2
                        && y1ass == y1 && y2ass == y2) {
                        if (x1 != x2 || y1 != y2) {
                            pol = (Polygon) this.echteKant.get(i);
                            x1 = pol.xpoints[0];
                            x2 = pol.xpoints[1];
                            y1 = pol.ypoints[0];
                            y2 = pol.ypoints[1];

                            Vektor2D verschOrtho = new Vektor2D(x1, y1);
                            verschOrtho.sub(new Vektor2D(x2, y2));
                            Vektor2D verschPar = new Vektor2D(verschOrtho);
                            verschPar.normal();
                            verschPar.mult(30);
                            verschOrtho.ortho();
                            verschOrtho.normal();
                            verschOrtho.mult(-10);
                            Vektor2D versch = new Vektor2D(verschPar);
                            versch.add(verschOrtho);
                           
                            x = (int) (((double) x1 + (double) x2) / 2.0
                                    + versch.x);
                            y = (int) (((double) y1 + (double) y2) / 2.0
                                    + versch.y);
                        }
                    }

                    i++;
                }
            }

            polygonListe.add(new Integer(x));
            polygonListe.add(new Integer(y));
            polygonListe.add(aktBeschr);
        }

        this.aktGraph = null;
        this.dopp.clear();
        this.urspKanten.clear();
        this.echteKant.clear();

        return polygonListe;
    }
   
    /**
     * Gibt einen Pfeil als Java-Polygon zur�ck, der in mehreren Segmenten
     * durch die �bergebenen Punkte verl�uft. Diese Methode basiert auf
     * <code>segmentPfeilPol2D</code>
     *
     * @param punkte       Die Punkte, durch die der Pfeil verlaufen soll.
     * @param dicken       Die Dicken des Pfeils an den Stellen der
     *                     Verlaufspunkte.
     * @param pfeilAnfang  Die Spitze des Pfeils am Beginn.
     * @param pfeilEnde    Die Spitze des Pfeils am Ende.
     * @param anfFaktor    Multiplikativer Faktor f�r die Gr��e der Enden.
     * @param endFaktor    Multiplikativer Faktor f�r die Gr��e der Enden.
     * @param gesamtskalierung  Skalierung des gesamten Polygons.
     * @param versch       Die Verschiebung.
     *
     * @return  Der Pfeil aus mehreren Segmenten.
     */
    public Polygon segmentPfeilPol(final Polygon2D punkte,
                                   final ArrayList<Double> dicken,
                                   final Polygon2D pfeilAnfang,
                                   final Polygon2D pfeilEnde,
                                   final Vektor2D    anfFaktor,
                                   final Vektor2D    endFaktor,
                                   final double    gesamtskalierung,
                                   final Vektor2D versch) {
       
        Polygon2D pfeilArr = this.segmentPfeilPol2D(
                punkte,
                dicken,
                pfeilAnfang,
                pfeilEnde,
                anfFaktor,
                endFaktor);
       
        return pfeilArr.toPol(gesamtskalierung, versch);
    }
   
    /**
     * Gibt einen Pfeil zur�ck, der in mehreren Segmenten durch die
     * �bergebenen Punkte verl�uft. Der Pfeil wird als Polygon2D
     * (und nicht als Java-Polygon) zur�ckgegeben.
     *
     * @param punkte       Die Punkte, durch die der Pfeil verlaufen soll.
     * @param dicken       Die Dicken des Pfeils an den Stellen der
     *                     Verlaufspunkte.
     * @param pfeilAnfang  Die Spitze des Pfeils am Beginn.
     * @param pfeilEnde    Die Spitze des Pfeils am Ende.
     * @param anfFaktor    Multiplikativer Faktor f�r die Gr��e der Enden.
     * @param endFaktor    Multiplikativer Faktor f�r die Gr��e der Enden.
     *
     * @return  Der Pfeil aus mehreren Segmenten.
     */
    public Polygon2D segmentPfeilPol2D(
            final Polygon2D punkte,
            final ArrayList<Double> dicken,
            final Polygon2D pfeilAnfang,
            final Polygon2D pfeilEnde,
            final Vektor2D            anfFaktor,
            final Vektor2D            endFaktor) {

        Vektor2D aktVekX;
        Vektor2D aktVekY;
        Vektor2D aktVek;
        Strecke2D p, q;
       
        if (punkte == null || punkte.size() < 2) {
            throw new RuntimeException("Zu wenige Segmente f�r Pfeil.");
        }
       
        ArrayList<Double> dick = dicken;
       
        if (dick == null) {
            dick = new ArrayList<Double>(punkte.size());
            for (int i = 0; i < punkte.size(); i++) {
                dick.add((double) this.pfeilDicke);
            }
        }
       
        Polygon2D pktList1 = new Polygon2D(punkte.size()
                                           + pfeilAnfang.size()
                                           + pfeilEnde.size());
        Polygon2D pktList2 = new Polygon2D(pktList1.size());

        // Pfeilanfang.
        Vektor2D normAnf = new Vektor2D(punkte.get(0));
        Vektor2D orthoAnf;
        normAnf.sub(punkte.get(1));
        normAnf.normal();
        orthoAnf = new Vektor2D(normAnf);
        orthoAnf.ortho();
        Iterator<Vektor2D> it1 = pfeilAnfang.iterator();
        Polygon2D zwisch = new Polygon2D(pfeilAnfang.size());
       
        while (it1.hasNext()) {
            aktVek = it1.next();
            aktVekX = new Vektor2D(orthoAnf);
            aktVekY = new Vektor2D(normAnf);
            aktVekX.mult(aktVek.x * anfFaktor.x * dick.get(0));
            aktVekY.mult(aktVek.y * anfFaktor.y * dick.get(0));
            aktVek = new Vektor2D(aktVekX);
            aktVek.add(aktVekY);
            aktVek.add(punkte.get(0));
            zwisch.add(aktVek);
        }
       
        for (int i = zwisch.size() - 1; i >= 0; i--) {
            pktList2.add(zwisch.get(i));
        }

        Polygon2D zwischPunkte;
       
        Vektor2D c1 = new Vektor2D(punkte.get(1));
        Vektor2D c2;
        c1.sub(punkte.get(0));
        c1.ortho();
        c1.normal();
        c1.mult((double) dick.get(0) / 2);
       
        Vektor2D p01 = new Vektor2D(punkte.get(0));
        Vektor2D p02 = new Vektor2D(p01);
        Vektor2D p11;
        Vektor2D p12;
       
        p01.add(c1);
        p02.sub(c1);
       
        pktList1.add(p01);
        pktList2.add(p02);
       
        for (int i = 1; i < punkte.size() - 1; i++) {
            zwischPunkte = fmg.fmg8.graphVis.zeichenModi.Geometrie2D.schnPkte(
                    punkte.get(i - 1),
                    punkte.get(i),
                    punkte.get(i + 1),
                    dick.get(i));
           
            p = new Strecke2D(
                    zwischPunkte.get(0),
                    zwischPunkte.get(1));
            q = new Strecke2D(
                    pktList1.get(pktList1.size() - 1),
                    pktList2.get(pktList2.size() - 1));
           
            if (p.schnPkt(q) == null) {
                pktList1.add(zwischPunkte.get(0));
                pktList2.add(zwischPunkte.get(1));
            } else {
                SonstMeth.log(SonstMeth.LOG_WARNING,
                              "Segment konnte nicht �berschneidungsfrei "
                              + "platziert werden um Pixel: " + punkte.get(i),
                              this.pars,
                              "",
                              punkte.get(i));
                pktList1.add(zwischPunkte.get(0));
                pktList2.add(zwischPunkte.get(1));
            }
        }
       
        c2 = new Vektor2D(punkte.get(punkte.size() - 1));
        c2.sub(punkte.get(punkte.size() - 2));
        c2.ortho();
        c2.normal();
        c2.mult((double) dick.get(punkte.size() - 1) / 2);
       
        p11 = new Vektor2D(punkte.get(punkte.size() - 1));
        p12 = new Vektor2D(p11);
       
        p11.add(c2);
        p12.sub(c2);
       
        pktList1.add(p11);
        pktList2.add(p12);
       
        // Pfeilspitze.
        Vektor2D normEnd = new Vektor2D(punkte.get(punkte.size() - 1));
        Vektor2D orthoEnd;
        normEnd.sub(punkte.get(punkte.size() - 2));
        normEnd.normal();
        orthoEnd = new Vektor2D(normEnd);
        orthoEnd.ortho();

        Iterator<Vektor2D> it2 = pfeilEnde.iterator();
       
        while (it2.hasNext()) {
            aktVek = it2.next();
            aktVekX = new Vektor2D(orthoEnd);
            aktVekY = new Vektor2D(normEnd);
            aktVekX.mult(aktVek.x * endFaktor.x * dick.get(dick.size() - 1));
            aktVekY.mult(aktVek.y * endFaktor.y * dick.get(dick.size() - 1));
            aktVek = new Vektor2D(aktVekX);
            aktVek.add(aktVekY);
            aktVek.add(punkte.get(punkte.size() - 1));
            pktList1.add(aktVek);
        }

        for (int i = pktList2.size() - 1; i >= 0; i--) {
            pktList1.add(pktList2.get(i));
        }

        return pktList1;
    }
   
    /**
     * Vereinfachter Pfeilerzeuger.
     *
     * @param punkte  Die Punkte, durch die der Pfeil laufen soll.
     * @return  Das Polygon.
     */
    public Polygon2D segmentPfeilPol2D(final Polygon2D punkte) {
        return this.segmentPfeilPol2D(
                punkte,
                null,
                PfeilMaster.EINFACHER_ABSCHLUSS,
                PfeilMaster.EINFACHE_SPITZE_2,
                new Vektor2D(1, 1),
                new Vektor2D(1, 1));
    }

    /**
     * Markiert die Ecken des Polygons durch Kreise in der Liste der zu
     * zeichnenden Objekte.
     *
     * @param p           Das Polygon.
     * @param l           Die Liste der Objekte.
     * @param markierung  Welche Ecken markiert werden sollen.
     * @param mark        Die Ausgabemerkmale f�r die markierten Knoten.
     * @param unmark      Die Ausgabemerkmale f�r die unmarkierten Knoten.
     * @param radius      Der Radius der Kreise.
     */
    public void markiereEcken(
            final Polygon p,
            final List<Object> l,
            final List<Integer> markierung,
            final AusgMerkm mark,
            final AusgMerkm unmark,
            final double radius) {
       
        Vektor2D v;
        Kreis2D k;
       
        for (int i = 0; i < p.npoints; i++) {
            if (markierung.contains(i)) {
                l.add(mark);
            } else {
                l.add(unmark);
            }
            v = new Vektor2D(p.xpoints[i], p.ypoints[i]);
            k = new Kreis2D(v.x, v.y, radius);
            l.add(k);
        }
    }
   
    /**
     * Erzeugt einen gestrichelten Pfeil mit zwei verschiedenen Segmenttypen.
     *
     * @param punkte           Die Punkte des Pfeils.
     * @param dicken           Die Dicken des Pfeils.
     * @param pfeilAnfang      Das Pfeilanfangspolygon.
     * @param pfeilEnde        Das Pfeilendepolygon.
     * @param anfFaktor        Der Anfangsfaktor.
     * @param endFaktor        Der Endfaktor.
     * @param farben           Eine beliebige Liste sich abwechselnder
     *                         Ausgabemerkmale. Ist hier ein Eintrag
     *                         <code>null</code>, wird kein Ausgabemerkmal
     *                         f�r die Segmente definiert.
     * @param strichLenFaktor  Multiplikativer Faktor f�r die L�nge eines
     *                         Segments bezogen auf die durchschnittliche
     *                         Dicke des Pfeils.
     * @param params           Die Parameter.
     * @return  Der gestrichelte Pfeil als Menge von Segmentpolygonen.
     */
    public Pol2DMitAusgMerkm[] gestrichelterPfeil(
            final Polygon2D punkte,
            final ArrayList<Double> dicken,
            final Polygon2D pfeilAnfang,
            final Polygon2D pfeilEnde,
            final Vektor2D  anfFaktor,
            final Vektor2D  endFaktor,
            final AusgMerkm[] farben,
            final double strichLenFaktor,
            final Parametersatz params) {

        SegSpez[] segBeschr;
        final double konstFakt = 3 * strichLenFaktor;
        double strLaeng;
        double durchDick = 0;
        double durchAbst = 0;
        double anzPunkte;
        int j;
        AusgMerkm farbe;
        Polygon2D anfang;
        Polygon2D ende;
        double mehrPunkte;
        double anzSegmente;
       
        if (dicken != null) {
            for (int i = 0; i < dicken.size(); i++) {
                durchDick += Math.abs(dicken.get(i));
            }
            durchDick /= dicken.size();
        } else {
            durchDick = Konstanten.PFEIL_DICKE;
        }

        for (int i = 0; i < punkte.size() - 2; i++) {
            durchAbst += punkte.get(i).distanz(punkte.get(i + 1));
        }
        durchAbst /= punkte.size() - 1;
        strLaeng = durchDick * konstFakt;
        anzPunkte = strLaeng / durchAbst;
       
        if (anzPunkte == 0) {
            return this.gestrichelterPfeil(
                    punkte,
                    dicken,
                    pfeilAnfang,
                    pfeilEnde,
                    anfFaktor,
                    endFaktor,
                    farben,
                    strichLenFaktor + 1,
                    params);
        }
       
        segBeschr = new SegSpez[(int) (punkte.size() / anzPunkte + 1)];

        anzSegmente = punkte.size() / anzPunkte;
        mehrPunkte = punkte.size() % anzPunkte;
        anzPunkte += mehrPunkte / ((int) anzSegmente + 1);

        SonstMeth.log(
                SonstMeth.LOG_DEBUG,
                "Segmente werden hinzugef�gt:",
                this.pars);
       
        j = 0;
        for (double i = 0; i <= punkte.size() - anzPunkte; i += anzPunkte) {
            farbe = farben[(int) j % farben.length];

            anfang = PfeilMaster.EINFACHER_ABSCHLUSS;
            ende = PfeilMaster.EINFACHER_ABSCHLUSS;
            if (i == 0) {
                anfang = pfeilAnfang;

                SonstMeth.log(
                        SonstMeth.LOG_DEBUG,
                        " " + anzPunkte,
                        this.pars,
                        "plain",
                        null);
            }
            if (i + anzPunkte > punkte.size() - anzPunkte) {
                ende = pfeilEnde;
                anzPunkte = punkte.size() - i - 1;

                SonstMeth.log(
                        SonstMeth.LOG_DEBUG,
                        " * " + j + " + " + anzPunkte + ".",
                        this.pars,
                        "plain",
                        null);
            }

            segBeschr[j] = new SegSpez(
                    farbe,
                    (int) i,
                    (int) (i + anzPunkte),
                    anfang,
                    ende,
                    anfFaktor,
                    endFaktor);
           
            j++;
        }

        return this.erzeugePfeilsegmente(punkte, dicken, segBeschr, params);
    }
   
    /**
     * Gibt eine beliebige Menge von beliebig zusammenh�ngenden Teilsegmenten
     * eines Pfeils zur�ck, wobei die Ausgabemerkmale f�r jedes zus.
     * Teilsegment einzeln eingestellt werden k�nnen.
     *
     * @param punkte       Die Punkte, durch die der Pfeil verlaufen soll.
     * @param dicken       Die Dicken des Pfeils an den Stellen der
     *                     Verlaufspunkte.
     * @param segBeschr    Die Beschreibungen einzelner Segmente.
     * @param params       Die Parameter.
     *
     * @return  Die Teilsegmente eines Pfeil aus mehreren Segmenten.
     */
    public Pol2DMitAusgMerkm[] erzeugePfeilsegmente(
            final Polygon2D punkte,
            final ArrayList<Double> dicken,
            final SegSpez[] segBeschr,
            final Parametersatz params) {
        Pol2DMitAusgMerkm[] segmente = new Pol2DMitAusgMerkm[segBeschr.length];
        Polygon2D aktPol;
        Polygon2D aktPunkte = new Polygon2D();
        ArrayList<Double> aktDicken = new ArrayList<Double>();
        PfeilMaster zeichnen = new PfeilMaster(params);
        AusgMerkm ausg;
        GradientPaint grad;
        Vektor2D p1Old, p2Old, p1, p2, v1, v2, zwisch;
        Color fuell, rahmen;
       
        for (int i = 0; i < segBeschr.length; i++) {
            if (segBeschr[i] != null) {
                aktPunkte.clear();
                aktDicken.clear();
                for (int j = segBeschr[i].getBeginn();
                 j <= segBeschr[i].getEnde(); j++) {
                    aktPunkte.add(punkte.get(j));
                    if (dicken != null) {
                        aktDicken.add(dicken.get(j));
                    } else {
                        aktDicken.add((double) Konstanten.PFEIL_DICKE);
                    }
                 }
               
                aktPol = zeichnen.segmentPfeilPol2D(
                        aktPunkte,
                        aktDicken,
                        segBeschr[i].getPfeilAnfang(),
                        segBeschr[i].getPfeilEnde(),
                        segBeschr[i].getFaktorAnfang(),
                        segBeschr[i].getFaktorEnde());
               
                ausg = segBeschr[i].getAusg();
               
                if (ausg != null && ausg.getGradPaint() != null) {
                    p1Old = new Vektor2D(
                            ausg.getGradPaint().getPoint1().getX(),
                            ausg.getGradPaint().getPoint1().getY());
                    p2Old = new Vektor2D(
                            ausg.getGradPaint().getPoint2().getX(),
                            ausg.getGradPaint().getPoint2().getY());
                    v1 = new Vektor2D(aktPunkte.get(aktPunkte.size() - 1));
                    v1.sub(aktPunkte.get(0));
                    v2 = new Vektor2D(v1);
                    v2.ortho();
                   
                    p1 = new Vektor2D(v1);
                    p1.mult(p1Old.y);
                    zwisch = new Vektor2D(v2);
                    zwisch.mult(p1Old.x);
                    p1.add(zwisch);
                    p1.add(aktPunkte.get(0));
                   
                    p2 = new Vektor2D(v1);
                    p2.mult(p2Old.y);
                    zwisch = new Vektor2D(v2);
                    zwisch.mult(p2Old.x);
                    p2.add(zwisch);
                    p2.add(aktPunkte.get(0));
                   
                    grad = new GradientPaint(
                            (float) p1.x,
                            (float) p1.y,
                            ausg.getGradPaint().getColor1(),
                            (float) p2.x,
                            (float) p2.y,
                            ausg.getGradPaint().getColor2());
                   
                    fuell = ausg.getFuellFarbe();
                    rahmen = ausg.getRahmenFarbe();
                   
                    ausg = new AusgMerkm(
                            grad,
                            ausg.holeRahmenDrucken(),
                            ausg.holeFuellungDrucken());
                   
                    ausg.setFuellFarbe(fuell);
                    ausg.setRahmenFarbe(rahmen);
                }
                segmente[i] = new Pol2DMitAusgMerkm(
                        aktPol,
                        ausg);
            }
        }
       
        return segmente;
    }
   
    /**
     * Main-Methode.
     *
     * @param args  Argumente.
     */
    public static void main(final String[] args) {
        Parametersatz params = new Parametersatz(args);
        params.ergaenze();
        PfeilMaster zeichnen = new PfeilMaster(params);
        AusgMerkm a1 = new AusgMerkm(Color.yellow, Color.black, true, true);
        AusgMerkm a2 = new AusgMerkm(Color.yellow, Color.black, true, true);
        List<Object> l;
        Polygon2D bez2 = new Polygon2D();
        ArrayList<Double> dicken = new ArrayList<Double>();
       
        for (double i = 0; i < Math.PI * 2; i += 0.0001) {
            bez2.add(new Vektor2D(Math.sin(i) * 10, Math.cos(i) * 10));
        }
       
        bez2 = bez2.normalisiere();

        for (double i = 0; i < bez2.size(); i++) {
            dicken.add(
                    Math.sin((i / bez2.size() * Math.PI * 4) * 4
                    + Math.sin(i / bez2.size() * Math.PI * 6) * 1
                    + Math.sin(i / bez2.size() * Math.PI * 8) * 2) * 3 + 4.5);
        }
       
        a1.setGradPaint(-3f, 0, Color.green, 3f, 0, Color.red);
        a2.setGradPaint(-3f, 0, Color.darkGray, 3f, 0, Color.blue);
       
        AusgMerkm[] ausg = new AusgMerkm[2];
        ausg[0] = a1;
        ausg[1] = a2;
       
        Pol2DMitAusgMerkm[] seg = zeichnen.gestrichelterPfeil(
                bez2,
                dicken,
                PfeilMaster.RUECK_PFEIL,
                PfeilMaster.RUECK_PFEIL,
                new Vektor2D(1, 1),
                new Vektor2D(1, 1),
                ausg,
                0.1,
                params);

        Polygon2D pol = new Polygon2D();
        pol.add(new Vektor2D(0, 15));
       
        l = Geometrie2D.erzeugeObjList(seg, 100, Vektor2D.NULL_VEKTOR);

        l.add(0, new AusgMerkm(Color.blue, Color.black, true, true));
        l.add(pol.toPol(100, Vektor2D.NULL_VEKTOR));
       
        Geometrie2D.saveObjectsToFile(l, "luke", "png", params);
    }
}
TOP

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

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.