/*
* Datei: ZeichenModusEA.java
* Autor(en): Lukas König
* Java-Version: 6.0
* Erstellt (vor): 24.11.2008
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
* author or licensor (but not in any way that suggests that they endorse
* you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
* distribute the resulting work only under the same or a similar license to
* this one.
*
* + Detailed license conditions (Germany):
* http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
* http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/
package eas.startSetup.marbBuilder.zeichenModi;
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.LinkedList;
import java.util.List;
import eas.math.geometry.Circle2D;
import eas.math.geometry.LineSegment2D;
import eas.math.geometry.Polygon2D;
import eas.math.geometry.Vector2D;
import eas.miscellaneous.StaticMethods;
import eas.simulation.spatial.sim2D.marbSimulation.endlAutomat.GlobaleMARBVariablen;
import eas.startSetup.GlobalVariables;
import eas.startSetup.ParCollection;
import eas.startSetup.marbBuilder.DargestellterGraph;
import eas.startSetup.marbBuilder.graph.Knoten;
/**
* 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 ArrowMaster 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;
/**
* 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 ParCollection pars;
/**
* Einfacher Abschluss, also ohne Spitze.
*/
public static final Pfeilspitze EINFACHER_ABSCHLUSS
= ArrowMaster.erzeugeKonstanteEnden(0);
/**
* Einfache Spitze.
*/
public static final Pfeilspitze EINFACHE_SPITZE_1
= ArrowMaster.erzeugeKonstanteEnden(1);
/**
* Einfache Spitze.
*/
public static final Pfeilspitze EINFACHE_SPITZE_2
= ArrowMaster.erzeugeKonstanteEnden(4);
/**
* Einfache Spitze.
*/
public static final Pfeilspitze EINFACHE_SPITZE_3
= ArrowMaster.erzeugeKonstanteEnden(5);
/**
* Doppelspitzes Ende.
*/
public static final Pfeilspitze DOPPELSPITZES_ENDE
= ArrowMaster.erzeugeKonstanteEnden(2);
/**
* Kugeliges Ende.
*/
public static final Pfeilspitze KUGEL_ENDE
= ArrowMaster.erzeugeKonstanteEnden(3);
/**
* Kugeliges Ende.
*/
public static final Pfeilspitze RUECK_PFEIL
= ArrowMaster.erzeugeKonstanteEnden(6);
/**
* Die Liste weiterer Pfeilspitzen.
*/
public static final LinkedList<Pfeilspitze> WEITERE_SPITZEN
= new LinkedList<Pfeilspitze>();
/**
* 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 Pfeilspitze erzeugeKonstanteEnden(final int nummer) {
Vector2D v;
Pfeilspitze a = null;
if (nummer == 0) {
a = new Pfeilspitze("Gerades Ende");
}
if (nummer == 1) {
a = new Pfeilspitze("Pfeilspitze 1");
v = new Vector2D(1.8, -0.7);
a.add(v);
v = new Vector2D(0, 5);
a.add(v);
v = new Vector2D(-1.8, -0.7);
a.add(v);
}
if (nummer == 2) {
a = new Pfeilspitze("Doppelspitzes Ende");
v = new Vector2D(Vector2D.NULL_VECTOR);
v.sub(new Vector2D(0, 0.3));
a.add(v);
}
if (nummer == 3) {
a = new Pfeilspitze(
eas.math.geometry.Geometry2D.bezierKurve(
new Vector2D(0.5, 0),
new Vector2D(5, 5),
new Vector2D(-5, 5),
new Vector2D(-0.5, 0),
0.0001),
"Kugelende");
}
if (nummer == 4) {
a = new Pfeilspitze("Pfeilspitze 2");
v = new Vector2D(1.8, 0);
a.add(v);
v = new Vector2D(0, 7);
a.add(v);
v = new Vector2D(-1.8, 0);
a.add(v);
}
if (nummer == 5) {
a = new Pfeilspitze("Pfeilspitze 3");
v = new Vector2D(2.3, -1.7);
a.add(v);
v = new Vector2D(2.85, -1.7);
a.add(v);
v = new Vector2D(0, 1.1);
a.add(v);
v = new Vector2D(-2.85, -1.7);
a.add(v);
v = new Vector2D(-2.3, -1.7);
a.add(v);
}
if (nummer == 6) {
ParCollection params = GlobalVariables.getPrematureParameters();
ArrowMaster zeichnen = new ArrowMaster(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 Vector2D(
-(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.nPoints(); i += 1) {
dicken.add(1.0);
}
a = new Pfeilspitze(
zeichnen.segmentPfeilPol2D(
bez,
dicken,
ArrowMaster.EINFACHER_ABSCHLUSS,
ArrowMaster.EINFACHE_SPITZE_1,
new Vector2D(1, 1),
new Vector2D(0.75, 0.75)),
"Rückpfeil");
}
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 par Die Parameter.
*/
public ArrowMaster(final int pfD,
final double pfSpL,
final ParCollection par) {
this.pfeilDicke = pfD;
this.pfeilSpLaenge = pfSpL;
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 ArrowMaster(final ParCollection par) {
this(ConstantsZeichenModi.PFEIL_DICKE,
ConstantsZeichenModi.PFEILSP_LAENGE,
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) {
double bezierConst = Math.max(
0.001,
this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.BEZIER_KONST));
int x1 = xx1;
int y1 = yy1;
int x2 = xx2;
int y2 = yy2;
double letztX;
double letztY;
Polygon dieseKante;
int konstVersch = (int) (ConstantsZeichenModi.PFEIL_DICKE * 2.3);
double vektorLen;
double x1d;
double x2d;
double y1d;
double y2d;
Polygon2D bez;
ArrayList<Double> dick;
Vector2D pk0, pk1, pk2, pk3;
if (!gebogen) {
Vector2D p1 = new Vector2D(xx1, yy1);
Vector2D p2 = new Vector2D(xx2, yy2);
Polygon2D a = new Polygon2D();
a.add(p1);
a.add(p2);
dick = new ArrayList<Double>(2);
dick.add(staerke * ConstantsZeichenModi.DICKEN_REG_ST
+ this.pfeilDicke);
dick.add((double) this.pfeilDicke);
return this.segmentPfeilPol(a,
dick,
DOPPELSPITZES_ENDE,
EINFACHE_SPITZE_1,
new Vector2D(1, 1),
new Vector2D(1, 1),
1,
Vector2D.NULL_VECTOR);
}
if (x1 == x2 && y1 == y2) {
letztX = x1 + ConstantsZeichenModi.KN_DURCHM / 2;
letztY = y1 + ConstantsZeichenModi.KN_DURCHM / 2;
pk0 = new Vector2D(letztX, letztY);
pk1 = new Vector2D(letztX + 80, letztY + 40);
pk2 = new Vector2D(letztX + 80,
y1 - ConstantsZeichenModi.KN_DURCHM / 2 + this.pfeilDicke / 2 - 30);
pk3 = new Vector2D(letztX + this.pfeilSpLaenge - 2,
y1 - ConstantsZeichenModi.KN_DURCHM / 2 + this.pfeilDicke / 2 - 9);
bez = eas.math.geometry.Geometry2D.bezierKurve(
pk0,
pk1,
pk2,
pk3,
bezierConst);
// if (this.pars.getEinfacheDar()) {
// dick = null;
// } else {
dick = new ArrayList<Double>(bez.nPoints());
for (double i = 0; i <= bez.nPoints(); i++) {
dick.add((bez.nPoints() - i) * staerke / bez.nPoints()
* ConstantsZeichenModi.DICKEN_REG_ST
+ this.pfeilDicke);
}
// }
return this.segmentPfeilPol(bez,
dick,
DOPPELSPITZES_ENDE,
EINFACHE_SPITZE_1,
new Vector2D(1, 1),
new Vector2D(1, 1),
1,
Vector2D.NULL_VECTOR);
} else {
Vector2D vv = new Vector2D(x2, y2);
vv.sub(new Vector2D(x1, y1));
vv.norm();
vv.mult(35);
x1 += vv.x;
y1 += vv.y;
x2 -= vv.x;
y2 -= vv.y;
// Die aktuelle Kante ist eine Doppelkante.
if (this.aktGraph != null && this.aktGraph.enthaeltPfeil(xx2, yy2, xx1, yy1)) {
x1d = x1;
x2d = x2;
y1d = y1;
y2d = 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 {
Vector2D v0 = new Vector2D(x2, y2);
v0.sub(new Vector2D(x1, y1));
v0.ortho();
v0.norm();
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);
Vector2D v = new Vector2D(x2, y2);
double dist = new Vector2D(x1, y1).distance(new Vector2D(x2, y2));
v.sub(new Vector2D(x1, y1));
v.norm();
v.mult(this.pfeilSpLaenge);
Vector2D v1 = new Vector2D(x1, y1);
Vector2D v2 = new Vector2D(x2, y2);
v2.sub(v);
Vector2D n1 = new Vector2D((x1 + x2) / 2, (y1 + y2) / 2);
Vector2D n2 = new Vector2D((x1 + x2) / 2, (y1 + y2) / 2);
v.ortho();
v.norm();
Vector2D zwisch = new Vector2D(x2, y2);
zwisch.sub(new Vector2D(x1, y2));
v.mult(Math.sqrt(Math.max(dist - 100, 0)) + 0.1);
n1.translate(v);
n2.translate(v);
bez = eas.math.geometry.Geometry2D.bezierKurve(
v1,
n1,
n2,
v2,
bezierConst);
// if (this.pars.getEinfacheDar()) {
// dick = null;
// } else {
dick = new ArrayList<Double>(bez.nPoints());
for (double i = 0; i <= bez.nPoints(); i++) {
dick.add((bez.nPoints() - i) * staerke / bez.nPoints()
* ConstantsZeichenModi.DICKEN_REG_ST
+ this.pfeilDicke);
}
// }
return this.segmentPfeilPol(bez,
dick,
DOPPELSPITZES_ENDE,
EINFACHE_SPITZE_1,
new Vector2D(1, 1),
new Vector2D(1, 1),
1,
Vector2D.NULL_VECTOR);
}
}
/**
* 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 double bezierConst) {
// 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 eas.math.geometry.Geometry2D.kreis(
new Vector2D(x, y),
31,
(int) (1 / bezierConst));
}
/**
* 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;
double bezierConst = Math.max(
0.001,
this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.BEZIER_KONST));
this.aktGraph = g;
if (this.pars.getParValueBoolean(eas.statistics.ConstantsStatistics.EINFACHE_DARSTELLUNG)) {
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.getParValueBoolean(eas.statistics.ConstantsStatistics.EINFACHE_DARSTELLUNG)) {
knotenFarbe = Color.LIGHT_GRAY;
} else {
knotenFarbe = ConstantsZeichenModi.MARKIERT_FUELL_FARBE;
}
} else {
if (this.pars.getParValueBoolean(eas.statistics.ConstantsStatistics.EINFACHE_DARSTELLUNG)) {
knotenFarbe = Color.white;
} else {
knotenFarbe = ConstantsZeichenModi.STANDARD_FUELL_FARBE;
}
}
ausgKnoten = new AusgMerkm(Color.BLACK,
knotenFarbe,
true,
true,
"Calibri",
Font.PLAIN,
14);
aktuellesPol = this.knotenEinfach(aktPunktK.x, aktPunktK.y, bezierConst);
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 = 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 = eas.simulation.ConstantsSimulation.befehlName(nBInt, this.pars) + nBeschr;
if (GlobaleMARBVariablen.GENERISCHE_ZUSTAENDE.get(nBInt) != null) {
aktBeschr = GlobaleMARBVariablen.GENERISCHE_ZUSTAENDE
.get(nBInt).stateName();
}
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 = 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 = this.echteKant.get(i);
x1 = pol.xpoints[0];
x2 = pol.xpoints[1];
y1 = pol.ypoints[0];
y2 = pol.ypoints[1];
Vector2D verschOrtho = new Vector2D(x1, y1);
verschOrtho.sub(new Vector2D(x2, y2));
Vector2D verschPar = new Vector2D(verschOrtho);
verschPar.norm();
verschPar.mult(30);
verschOrtho.ortho();
verschOrtho.norm();
verschOrtho.mult(-10);
Vector2D versch = new Vector2D(verschPar);
versch.translate(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 Pfeilspitze pfeilAnfang,
final Pfeilspitze pfeilEnde,
final Vector2D anfFaktor,
final Vector2D endFaktor,
final double gesamtskalierung,
final Vector2D 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 List<Double> dicken,
final Pfeilspitze pfeilAnfang,
final Pfeilspitze pfeilEnde,
final Vector2D anfFaktor,
final Vector2D endFaktor) {
Vector2D aktVekX;
Vector2D aktVekY;
Vector2D aktVek;
LineSegment2D p, q;
if (punkte == null || punkte.nPoints() < 2) {
throw new RuntimeException("Zu wenige Segmente für Pfeil.");
}
List<Double> dick = dicken;
if (dick == null) {
dick = new ArrayList<Double>(punkte.nPoints());
for (int i = 0; i < punkte.nPoints(); i++) {
dick.add((double) this.pfeilDicke);
}
}
Polygon2D pktList1 = new Polygon2D();
Polygon2D pktList2 = new Polygon2D();
// Pfeilanfang.
Vector2D normAnf = new Vector2D(punkte.get(0));
Vector2D orthoAnf;
normAnf.sub(punkte.get(1));
normAnf.norm();
orthoAnf = new Vector2D(normAnf);
orthoAnf.ortho();
Iterator<Vector2D> it1 = pfeilAnfang.iterator();
Polygon2D zwisch = new Polygon2D();
while (it1.hasNext()) {
aktVek = it1.next();
aktVekX = new Vector2D(orthoAnf);
aktVekY = new Vector2D(normAnf);
aktVekX.mult(aktVek.x * anfFaktor.x * dick.get(0));
aktVekY.mult(aktVek.y * anfFaktor.y * dick.get(0));
aktVek = new Vector2D(aktVekX);
aktVek.translate(aktVekY);
aktVek.translate(punkte.get(0));
zwisch.add(aktVek);
}
for (int i = zwisch.nPoints() - 1; i >= 0; i--) {
pktList2.add(zwisch.get(i));
}
Polygon2D zwischPunkte;
Vector2D c1 = new Vector2D(punkte.get(1));
Vector2D c2;
c1.sub(punkte.get(0));
c1.ortho();
c1.norm();
c1.mult(dick.get(0) / 2);
Vector2D p01 = new Vector2D(punkte.get(0));
Vector2D p02 = new Vector2D(p01);
Vector2D p11;
Vector2D p12;
p01.translate(c1);
p02.sub(c1);
pktList1.add(p01);
pktList2.add(p02);
for (int i = 1; i < punkte.nPoints() - 1; i++) {
zwischPunkte = eas.math.geometry.Geometry2D.schnPkte(
punkte.get(i - 1),
punkte.get(i),
punkte.get(i + 1),
dick.get(i));
p = new LineSegment2D(
zwischPunkte.get(0),
zwischPunkte.get(1));
q = new LineSegment2D(
pktList1.get(pktList1.nPoints() - 1),
pktList2.get(pktList2.nPoints() - 1));
if (p.intersects(q) == null) {
pktList1.add(zwischPunkte.get(0));
pktList2.add(zwischPunkte.get(1));
} else {
StaticMethods.log(StaticMethods.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 Vector2D(punkte.get(punkte.nPoints() - 1));
c2.sub(punkte.get(punkte.nPoints() - 2));
c2.ortho();
c2.norm();
c2.mult(dick.get(punkte.nPoints() - 1) / 2);
p11 = new Vector2D(punkte.get(punkte.nPoints() - 1));
p12 = new Vector2D(p11);
p11.translate(c2);
p12.sub(c2);
pktList1.add(p11);
pktList2.add(p12);
// Pfeilspitze.
Vector2D normEnd = new Vector2D(punkte.get(punkte.nPoints() - 1));
Vector2D orthoEnd;
normEnd.sub(punkte.get(punkte.nPoints() - 2));
normEnd.norm();
orthoEnd = new Vector2D(normEnd);
orthoEnd.ortho();
Iterator<Vector2D> it2 = pfeilEnde.iterator();
while (it2.hasNext()) {
aktVek = it2.next();
aktVekX = new Vector2D(orthoEnd);
aktVekY = new Vector2D(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 Vector2D(aktVekX);
aktVek.translate(aktVekY);
aktVek.translate(punkte.get(punkte.nPoints() - 1));
pktList1.add(aktVek);
}
for (int i = pktList2.nPoints() - 1; i >= 0; i--) {
pktList1.add(pktList2.get(i));
}
return pktList1;
}
public Polygon2D segmentPfeilPol2D(
final Polygon2D punkte,
final List<Double> dicken) {
return this.segmentPfeilPol2D(
punkte,
dicken,
ArrowMaster.EINFACHER_ABSCHLUSS,
ArrowMaster.EINFACHE_SPITZE_2,
new Vector2D(1, 1),
new Vector2D(1, 1));
}
/**
* 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,
ArrowMaster.EINFACHER_ABSCHLUSS,
ArrowMaster.EINFACHE_SPITZE_2,
new Vector2D(1, 1),
new Vector2D(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) {
Vector2D v;
Circle2D k;
for (int i = 0; i < p.npoints; i++) {
if (markierung.contains(i)) {
l.add(mark);
} else {
l.add(unmark);
}
v = new Vector2D(p.xpoints[i], p.ypoints[i]);
k = new Circle2D(v.x, v.y, radius);
l.add(k);
}
}
/**
* Erzeugt einen gestrichelten Pfeil mit 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 Pfeilspitze pfeilAnfang,
final Pfeilspitze pfeilEnde,
final Vector2D anfFaktor,
final Vector2D endFaktor,
final AusgMerkm[] farben,
final double strichLenFaktor,
final ParCollection params) {
SegSpez[] segBeschr;
final double konstFakt = 3 * strichLenFaktor;
double strLaeng;
double durchDick = 0;
double durchAbst = 0;
double anzPunkte;
int j;
AusgMerkm farbe;
Pfeilspitze anfang;
Pfeilspitze 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 = ConstantsZeichenModi.PFEIL_DICKE;
}
for (int i = 0; i < punkte.nPoints() - 2; i++) {
durchAbst += punkte.get(i).distance(punkte.get(i + 1));
}
durchAbst /= punkte.nPoints() - 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.nPoints() / anzPunkte + 1)];
anzSegmente = punkte.nPoints() / anzPunkte;
mehrPunkte = punkte.nPoints() % anzPunkte;
anzPunkte += mehrPunkte / ((int) anzSegmente + 1);
StaticMethods.log(
StaticMethods.LOG_DEBUG,
"Segmente werden hinzugefügt:",
this.pars);
j = 0;
for (double i = 0; i <= punkte.nPoints() - anzPunkte; i += anzPunkte) {
farbe = farben[j % farben.length];
anfang = ArrowMaster.EINFACHER_ABSCHLUSS;
ende = ArrowMaster.EINFACHER_ABSCHLUSS;
if (i == 0) {
anfang = pfeilAnfang;
StaticMethods.log(
StaticMethods.LOG_DEBUG,
" " + anzPunkte,
this.pars,
"plain",
null);
}
if (i + anzPunkte > punkte.nPoints() - anzPunkte) {
ende = pfeilEnde;
anzPunkte = punkte.nPoints() - i - 1;
StaticMethods.log(
StaticMethods.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 ParCollection params) {
Pol2DMitAusgMerkm[] segmente = new Pol2DMitAusgMerkm[segBeschr.length];
Polygon2D aktPol;
Polygon2D aktPunkte = new Polygon2D();
ArrayList<Double> aktDicken = new ArrayList<Double>();
ArrowMaster zeichnen = new ArrowMaster(params);
AusgMerkm ausg;
GradientPaint grad;
Vector2D 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) ConstantsZeichenModi.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 Vector2D(
ausg.getGradPaint().getPoint1().getX(),
ausg.getGradPaint().getPoint1().getY());
p2Old = new Vector2D(
ausg.getGradPaint().getPoint2().getX(),
ausg.getGradPaint().getPoint2().getY());
v1 = new Vector2D(aktPunkte.get(aktPunkte.nPoints() - 1));
v1.sub(aktPunkte.get(0));
v2 = new Vector2D(v1);
v2.ortho();
p1 = new Vector2D(v1);
p1.mult(p1Old.y);
zwisch = new Vector2D(v2);
zwisch.mult(p1Old.x);
p1.translate(zwisch);
p1.translate(aktPunkte.get(0));
p2 = new Vector2D(v1);
p2.mult(p2Old.y);
zwisch = new Vector2D(v2);
zwisch.mult(p2Old.x);
p2.translate(zwisch);
p2.translate(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;
}
/**
* @return Alle Pfeilspitzen.
*/
public static ArrayList<Pfeilspitze> getSpitzen() {
ArrayList<Pfeilspitze> spitzen = new ArrayList<Pfeilspitze>(7);
spitzen.add(ArrowMaster.DOPPELSPITZES_ENDE);
spitzen.add(ArrowMaster.EINFACHE_SPITZE_1);
spitzen.add(ArrowMaster.EINFACHE_SPITZE_2);
spitzen.add(ArrowMaster.EINFACHE_SPITZE_3);
spitzen.add(ArrowMaster.EINFACHER_ABSCHLUSS);
spitzen.add(ArrowMaster.KUGEL_ENDE);
spitzen.add(ArrowMaster.RUECK_PFEIL);
spitzen.addAll(ArrowMaster.WEITERE_SPITZEN);
return spitzen;
}
// /**
// * Main-Methode.
// *
// * @param args Argumente.
// */
// public static void main(final String[] args) {
// ParCollection params = new ParCollection(args);
// params.ergaenze();
// PfeilMaster zeichnen = new PfeilMaster(params);
// List<Object> l = new ArrayList<Object>();
// Polygon2D bez2 = new Polygon2D();
//
// bez2 = Geometry2D.bezierKurve(
// new Vector2D(0, 0),
// new Vector2D(50, 0),
// new Vector2D(50, -20),
// new Vector2D(100, -20),
// 0.0001);
//
// bez2 = bez2.normalisiere(params);
//
// Polygon2D seg = zeichnen.segmentPfeilPol2D(
// bez2,
// null,
// PfeilMaster.DOPPELSPITZES_ENDE,
// PfeilMaster.EINFACHE_SPITZE_1,
// new Vector2D(1, 1),
// new Vector2D(1, 1));
//
// l.add(seg.toPol(5, Vector2D.NULL_VECTOR));
// l.add(0, new AusgMerkm(Color.black, Color.yellow, true, true));
// params.setStdPfad(
// "C:\\Eig");
//
// Geometry2D.saveObjectsToFile(l, "luke", "png", params);
// }
}