dokumentation

Werbung
Simulation und Visualisierung eines
Vogelschwarms
Hausarbeit zum Fach Systemprogrammierung
WS 2005 / 2006
Holger Rohde
618928
[email protected]
Inhaltsverzeichnis
1
2
3
4
5
Projektbeschreibung ................................................................................................................ 4
1.1
Projektthema.................................................................................................................... 4
1.2
Ziele ................................................................................................................................. 4
Benutzerdokumentation .......................................................................................................... 5
2.1
Übersetzen und Ausführen .............................................................................................. 5
2.2
Simulationssteuerung ...................................................................................................... 5
2.3
Informationsbereich ........................................................................................................ 7
2.4
Animationsansicht ........................................................................................................... 8
Detaildokumentation ............................................................................................................... 8
3.1
Algorithmus ..................................................................................................................... 8
3.2
Parallelisierung .............................................................................................................. 10
3.2.1
Sequentielle Implementierung............................................................................... 11
3.2.2
Parallele Implementierung .................................................................................... 13
3.3
Programmoberfläche ..................................................................................................... 17
3.4
Animation ...................................................................................................................... 19
3.4.1
Licht ...................................................................................................................... 19
3.4.2
Umgebung ............................................................................................................. 20
3.4.3
Vögel ..................................................................................................................... 21
3.4.4
Hindernisvermeidung ............................................................................................ 22
3.5
Leistungsvergleich ........................................................................................................ 23
Fazit ....................................................................................................................................... 27
Anhang .................................................................................................................................. 27
5.1
Quellenverzeichnis ........................................................................................................ 27
5.2
Quellcode ...................................................................................................................... 28
5.2.1
Packet ani .............................................................................................................. 28
5.2.1.1 AbstractFlock.java ............................................................................................ 28
5.2.1.2 AbstractFlockManager.java .............................................................................. 34
5.2.1.3 AniPanel.java .................................................................................................... 37
5.2.1.4 Bird.java ............................................................................................................ 40
5.2.1.5 BirdModel.java .................................................................................................. 45
5.2.1.6 FlockManagerSeq.java ..................................................................................... 47
5.2.1.7 FlockManagerThr.java ..................................................................................... 48
5.2.1.8 FlockSeq.java .................................................................................................... 50
5.2.1.9 FlockThr.java .................................................................................................... 52
5.2.1.10
GlobalLight.java ........................................................................................... 55
5.2.1.11
Obstacle.java ................................................................................................. 56
5.2.1.12
World.java ..................................................................................................... 58
5.2.2
Packet gui .............................................................................................................. 61
5.2.2.1 ControlPanel.java ............................................................................................. 61
5.2.2.2 InfoPanel.java ................................................................................................... 70
5.2.2.3 MainFrame.java ................................................................................................ 72
5.2.3
Packet i18n ............................................................................................................ 77
5.2.3.1 Messages.java ................................................................................................... 77
5.2.3.2 MessagesBundle_en_US.properties .................................................................. 79
5.2.3.3 MessagesBundle.properties............................................................................... 80
5.2.4
Packet util .............................................................................................................. 81
5.2.4.1 AppSetup.java .................................................................................................... 81
5.2.4.2 BirdList.java ...................................................................................................... 83
5.2.4.3 ExtScrollBar,java .............................................................................................. 84
5.2.4.4 FlockList.java .................................................................................................... 87
5.2.4.5 ParameterSet.java ............................................................................................. 88
5.2.4.6 Timer.java ......................................................................................................... 94
5.2.5
Skripte zum Übersetzen und Ausführen................................................................ 96
5.2.5.1 benchmark.bat ................................................................................................... 96
5.2.5.2 benchmark.sh..................................................................................................... 97
5.2.5.3 compile.bat ........................................................................................................ 97
5.2.5.4 compile.sh .......................................................................................................... 97
5.2.5.5 run.bat ............................................................................................................... 98
5.2.5.6 run.sh ................................................................................................................. 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 4 von 98
1 Projektbeschreibung
1.1 Projektthema
Als Thema für diese Hausarbeit wurde die Simulation des Schwarmverhaltens von Vögeln
gewählt. Als Basis für diese Simulation diente ein von Craig Reynolds 1987 veröffentlichtes
Model zur Erzeugung von Schwarmverhalten [1], [2]. Dieses beschreibt Methoden zur
realitätsnahen Simulation des Verhaltens verschiedener Tierarten in Schwärmen und wurde
mittlerweile in zahlreichen Ausarbeitungen behandelt. Auch bei der Produktion bekannter Filme
wurde es bereits eingesetzt. So zum Beispiel im Film Batman Returns von 1992 zur Animation
von Fledermaus- und Pinguinschwärmen1.
1.2 Ziele
Neben der Erläuterung und Implementierung des Verfahrens zur Simulation des für Vögel und
andere Tierarten typischen Schwarmverhaltens, war es Ziel dieser Projektarbeit die
Parallelisierbarkeit des zum Einsatz kommenden Algorithmus zu Betrachten. Bei entsprechenden
Ergebnissen dieser Betrachtung sollte eine parallele Variante umgesetzt werden und diese mit
der zuvor erstellten sequentiellen Variante auf verschiedenen Rechnern bezüglich der Leistung
verglichen werden. Da eine Simulation in diesem Bereich ohne eine entsprechende
Visualisierung wenig sinnvoll ist, war die Animation des Schwarmverhaltens mittels Java3D
eins der weiteren Ziele. Darüber hinaus wurden weitere optionale Ziel definiert. Dies waren die
Integration von zu umfliegenden Hindernissen sowie die Verbesserung der Visualisierung im
Bereich der Vogel- und Umgebungsdarstellung. Ein weiteres optionales Ziel war die Steuerung
der Simulationsparameter. Hier stellte sich jedoch schnell heraus, dass ohne dieses Merkmal ein
sinnvoller Leistungsvergleich nicht möglich sein würde, weshalb dieser Punkt zu einem festen
Teil der Arbeit wurde.
1
Information entnommen aus [2]
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 5 von 98
2 Benutzerdokumentation
2.1 Übersetzen und Ausführen
Das Programm benötigt eine installierte Java-Laufzeitumgebung2 der Firma Sun in der Version
1.4 oder höher. Andere Versionen sollten prinzipiell Funktionieren wurden jedoch nicht getestet.
Zusätzlich wird eine installierte Version der Java3D-Bibliothek3 für die Animation benötigt.
Entwickelt und getestet wurde die Anwendung mit Version 1.3.2. Andere Versionen sollten
jedoch auch hier funktionieren. Um das Übersetzen und Ausführen des Quellcode zu erleichtern
werden entsprechende Skripte4 für Windows und Unix bereitgestellt. Falls andere Argumente an
das Programm übergeben werden sollen, können diese entsprechend angepasst werden.
Informationen hierzu sind in den einzelnen Skripten enthalten. Die beim Programmstart
möglichen Optionen werden später auch noch genauer erläutert.
2.2 Simulationssteuerung
Die Steuerung des entwickelten Programms kann auf zwei verschiedenen Ebenen erfolgen. Die
Programmoberfläche ermöglicht die Variation der für die Simulation relevanten Faktoren über
Schieberegler und einige die Animation betreffende Einstellungen über ein Menü (Abb. 2).
Zusätzlich können der Anwendung beim Start eine Reihe von Argumenten übergeben werden.
Die in der Programmoberfläche zur Verfügung stehenden Schieberegler sind in vier Gruppen
gegliedert, die jeweils eine Schaltfläche zum Zurücksetzen auf die im Programm vorgegebenen
Standardwerte bieten. Die ersten drei Gruppen beziehen sich auf die Parameter des Algorithmus
und sind jeweils nochmals nach den für den Algorithmus relevanten Kräften „Zusammenhalt“,
„Vermeidung“ und „Ausrichtung“ unterteilt. Die letzte Gruppe beinhaltet die Regler für die
maximale Geschwindigkeit, die maximale Kraft und die Anzahl der Vögel.
Mit den in der ersten Gruppe enthaltenen Schiebereglern kann der Sichtwinkel des Vogels
beeinflusst werden (Abb. 2a). Dieser kann für alle Kräfte zwischen einem und hundertachtzig
Grad liegen, wobei letzteres dazu führt, dass der Vogel einen Rundumblick besitzt. Der
tatsächliche Sichtwinkel ist also doppelt so hoch wie die Einstellung für den Algorithmus. Die
zweite Gruppe steuert die maximale Distanz die Vögel besitzen dürfen um sich gegenseitig als
Nachbarn zu betrachten (Abb. 2b). Mit der dritten Schiebereglergruppe kann die Gewichtung der
einzelnen Kräfte variiert werden (Abb. 2.1c). Sollen die Vögel also zum Beispiel einen größeren
2
http://w ww.java.com/
https://java3d.dev.java.net/binary-builds.html
4
compile.bat, compile.sh, run.bat und run.sh im Projektverzeichnis
3
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 6 von 98
Abstand einhalten, könnte der Regler für die „Vermeidung“ höher und der Regler für den
„Zusammenhalt“ niedriger eingestellt werden. Die letzte Gruppe ermöglicht die Steuerung
verschiedener Parameter (Abb. 2.1d). Der erste Regler legt die maximale Kraft fest die auf den
Vogel wirken darf. Die Kraft beeinflusst den Vogel bezüglich seiner Beweglichkeit. Er würde es
bei einer sehr niedrigen Kraft zum Beispiel nicht schaffen seine Richtung vor dem erreichen der
Begrenzung schnell genug zu ändern was zur Folge hätte das er die Welt kurzzeitig verläst. Der
zweite Regler dieser Gruppe steuert die maximale Geschwindigkeit des Vogels. Geschwindigkeit
und Kraft sollten immer in einem entsprechenden Verhältnis stehen. Eine hohe Geschwindigkeit
erfordert auch eine höhere Kraft und umgekehrt. Mit dem letzen Regler kann die Anzahl der
Vögel gesteuert werden. Jeder Schwarm der Simulation besitzt immer die gleiche Anzahl an
Vögeln die dem Wert des Reglers entspricht. Eine weitere Möglichkeit Einfluss auf die
Animation zu nehmen bietet das Menü des Programms (Abb. 2e). Neben dem Beenden bietet es
drei weitere Einstellungsmöglichkeiten. Mittels des ersten Punkts (Vogel Begrenzung), kann der
das Vogelmodell umgebende Würfel ein- und ausgeschaltet werden. Dieser dient der
Visualisierung eines imaginären Felds das den Vogel umgibt und diesen beim Auftreffen auf ein
Hindernis informiert. Dies wird durch das rote (Weltbegrenzung) bzw. gelbe (Hindernisse)
Aufleuchten der Box dargestellt. Der zweite Punkt ermöglicht das Ein- und Ausschalten der
Weltbegrenzungen. Diese sind zwar weiter vorhanden und hindern den Vogel am davon fliegen,
werden aber nicht mehr durch den Quader dargestellt. Der letzte Menüpunkt ermöglicht das Einund Ausschalten der durch die Säulen dargestellten Hindernisse. Anders als bei der
Weltbegrenzung wird mit dieser Option auch das Umfliegen der Hindernisse an sich
ausgeschaltet.
Zusätzlich zu den Reglern, Schaltflächen und Menüs können Einstellungen des Programms über
Argumente beim Programmstart (am einfachsten durch Abändern der zur Verfügung gestellten
Startskripte) vorgenommen werden. Folgende Parameter stehen zur Verfügung:

-d:
Einschalten von Statusausgaben auf der Konsole

-b:
Anzahl der Vögel pro Schwarm / Anzahl muss ohne Leerzeichen an den
Parameter angehängt werden

-t:
Testmodus zur Leistungsmessung aktivieren

-p:
Parallele Berechnung der Simulationsdaten / es wird ein Thread pro Schwarm
genutzt

-f:
Anzahl der Vogelschwärme / Anzahl muss ohne Leerzeichen an den
Parameter angehängt werden
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 7 von 98
Abbildung 2.1: Die Programmoberfläche
2.3 Informationsbereich
Unterhalb des Menüs der Anwendung befindet sich der Informationsbereich der Simulation. Hier
werden die aktuellen Messwerte des Algorithmus angezeigt. Es können die folgenden, den
Algorithmus betreffenden, Werte abgelesen werden:

Rechenzeit der aktuellen Iteration in Millisekunden

Durchschnittszeit aller Iterationen in Millisekunden

Gesamtrechenzeit in Millisekunden

Anzahl der durchlaufenen Iterationen
Die Informationen werden alle 5 Iterationen aktualisiert.
Holger Rohde
WS 2005/2006
Seite 8 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
2.4 Animationsansicht
Um einen besseren Überblick über die Animation zu ermöglichen, kann die komplette Welt mit
der linken Maustaste gedreht werden.
3 Detaildokumentation
Hinweis: Die in diesem Kapitel enthalten Klassendiagramme sollen einen Überblick über die
jeweiligen Zusammenhänge bieten. Um dies zu erleichtern wurden alle für das Verständnis nicht
relevanten Attribute, Methoden und Assoziationen ausgeblendet!
3.1 Algorithmus
Wie bereits in der Projektbeschreibung angesprochen, basiert der in dieser Arbeit verwendete
Algorithmus auf dem von Craig Reynolds 1987 veröffentlichten Model zur Simulation von
Schwarmverhalten. Dieses sieht eine einzelne Betrachtung aller Vögel eines Schwarms und nicht
des Schwarms als Ganzes vor. Um das typische Verhalten nachzuahmen werden für jeden Vogel
Regeln definiert die dieser für die Vögel in seiner direkten Umgebung zu beachten hat. So
versucht der Vogel einerseits in der Nähe der anderen Vögel zu bleiben, gleichzeitig achtet er
aber darauf nicht mit diesen zusammen zu stoßen. Des Weiteren versucht der Vogel sich der
Flugrichtung seiner Nachbarn anzupassen. Um dieses Verhalten der Vögel zu erreichen, müssen
für jeden Vogel drei Kräfte berechnet werden. Diese von Reynolds mit „cohesion“, „alignment“,
und „seperation“ bezeichneten Kräfte (in der deutschen Version des Programms
„Zusammenhalt“, „Ausrichtung“ und „Vermeidung“) sollen nun anhand eines Vogels und seiner
Nachbarn erläutert werden. Die Kraft „cohesion“ sorgt für den Zusammenhalt des
Vogelschwarms. Sie zieht den Vogel zur mittleren Position seiner Nachbarn (Abb. 3.1a). Die
Kraft „seperation“ verhindert ein Kollidieren der Vögel. Zu diesem Zweck wird eine von den
anderen Vögeln wegführende Kraft bestimmt und addiert (Abb. 3.1b). Die Kraft „alignment“
schließlich sorgt davor, dass der Vogel sich der Flugrichtung seiner Nachbarn anpasst. Zu
diesem Zweck wird die mittlere Richtung der anderen Vögel bestimmt und auf die Richtung des
Vogels addiert (Abb. 3.1c).
Holger Rohde
WS 2005/2006
Seite 9 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
(a) cohesion
(b) seperation
(c) alignment
Abbildung 3.1: Kräfte durch die der Vogel beeinflusst wird
Da jeder Vogel nur auf seine Nachbarn reagieren soll, benötigt man noch eine Methode um diese
zu bestimmen. Nach Reynolds ist ein Vogel genau dann ein Nachbar wenn er nicht weiter als
eine vorgegebene Distanz entfernt ist und zusätzlich in einem durch einen Winkel begrenzten
Bereich liegt (Abb. 3.2). Dieser Winkel definiert das Sichtfeld des Vogels ausgehend von seiner
aktuellen Flugrichtung.
Distanz
Winkel
Winkel
Abbildung 3.2: Sichtbereich des Vogels
Jede Iteration des Algorithmus erfordert also für jeden Vogel eine Überprüfung welche Vögel
sich in seinem Umfeld befinden. Für jeden Nachbarvogel werden dann die oben beschriebenen
Kräfte berechnet und auf den Vogel angewendet. Die konkreten Berechnungen der einzelnen
Kräfte und die Bestimmung der Nachbarn wurden anhand des oben beschrieben Models und
zweier Ausarbeitungen zum Thema von Andrew Davison und Olaf Schnapauff entwickelt [3],
[4]. Diese befinden sich im Quelltext in den Methoden seperation(), cohesion() und alignment()
der Klasse AbstractFlock sowie in isNeighbor() der Klasse Bird.
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 10 von 98
3.2 Parallelisierung
  5 wird mit steigender Vogelzahl eine erhebliche
Aufgrund der Komplexität von O n 2
Rechenzeit benötigt. Deshalb erschien es als durchaus sinnvoll über eine parallele Variante des
Algorithmus nachzudenken. Betrachtet wurden nur Lösungen die auf Threads basieren.
Um das Problem parallel berechnen zu können muss zuerst geklärt werden, ob die Aufgabe in
Teilaufgaben zerlegt werden kann. Dies scheint auf den ersten Blick kein Problem darzustellen,
da für jeden Vogel eine separate Berechnung durchzuführen ist. Hierbei muss man jedoch
beachten, dass für jede Berechnung eines Vogels, die Daten der anderen Vögel nötig sind. Dieses
Problem kann jedoch durch eine einfache Anpassung des Ablaufs gelöst werden. Der
Algorithmus wird dazu in zwei Teile zerlegt. Im ersten Schritt werden für jeden Vogel die
entsprechenden Kräfte bestimmt und zwischengespeichert. Erst nach Beendigung der Berechung
werden diese Kräfte dann auf die Vögel angewendet. Dadurch können die im ersten Schritt
anfallenden Berechnungen parallel ablaufen ohne sich gegenseitig zu beeinflussen. Nachdem
klar ist, dass die Aufgabe aufteilbar ist, gilt es noch die Frage zu klären wie die Zerlegung in
Teilaufgaben erfolgen kann. Ein möglicher Ansatz ist die Verwendung eines Threads pro Vogel.
Die dadurch entstehende große Anzahl an Threads würde das Programm aber durch die für die
Erstellung und den Wechsel zwischen den einzelnen Threads benötigte Zeit unnötig
verlangsamen. Es ist daher sinnvoller die Vögel auf eine bestimmte Anzahl von Threads
aufzuteilen. So könnten zum Beispiel für n Vögel m Threads erstellt werden, wobei jeder
Thread im Durchschnitt
n
Vögel berechnet. Die Vögel könnte man dann entweder jeweils vor
m
Beginn der Berechnung komplett auf die zur Verfügung stehenden Threads aufteilen, oder
nacheinander an jeweils rechenwillige Threads übergeben. In diesem Fall würde das
Hauptprogramm die Vögel anhand einer bestimmten Strategie aufteilen, im einfachsten Fall
immer eine konstante Anzahl. Ein anderer Ansatz ist es, die Vögel von vornherein in gleich
große Gruppen einzuteilen die unabhängig voneinander sind. Man würde also aus einem
Vogelschwarm mehrere unabhängige Vogelschwärme machen. Dies hätte zwar zur Folge, dass
sich die einzelnen Schwärme untereinander nicht beachten, würde die Komplexität des
5
n := Anzahl Vögel
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 11 von 98
 n 26
 verringern. In diesem Fall könnte man pro
Algorithmus aber auch von O n 2 auf O 

m


 
Schwarm einfach einen Thread verwenden und die Aufteilung der Vögel einsparen.
Unabhängig von der für die Aufteilung der Aufgabe verwendeten Strategie sollten die Threads
für die gesamte Laufzeit des Programms existieren, da das ständige Erzeugen von neuen Threads
zu aufwendig wäre. Dies macht es für jede der Varianten erforderlich, eine Steuerung zu
realisieren, die es dem Hauptprogramm ermöglicht die Berechnung innerhalb des Threads zu
starten. Der Thread muss wiederum das Hauptprogramm informieren wenn er mit der
Berechnung fertig ist. In der Programmiersprache Java bietet sich hierfür die Verwendung der
Methoden wait() und notify() aus der Klasse Object an.
Anmerkung:
Weitere sehr interessant erscheinende Ansätze sind die Java-Implementierungen des Message
Passing Interface (MPI)7 bzw. der Parallel Virtual Machine (PVM)8. Diese konnten in der zur
Verfügung stehenden Zeit aber leider nicht weiter verfolgt werden.
3.2.1 Sequentielle Implementierung
Die sequentielle Variante des Algorithmus wurde in den Klassen FlockManagerSeq, FlockSeq
und Bird umgesetzt. Die Klassen FlockManagerSeq und FlockSeq sind Erweiterungen der
Klassen AbstractFlockManager und AbstractFlock. Diese beiden abstrakten Klassen bilden die
Schnittmenge der sequentiellen und parallelen Variante. Zur Vereinfachung wurden die Klassen
BirdList und FlockList erstellt. Diese ermöglichen die Ablage der Vogel und Schwarmobjekte
und erweitern die Klasse ArrayList um Methoden zum Abrufen dieser Objekte ohne
Typumwandlung von Object (Rückgabetyp der Methode get() aus ArrayList) zu Bird oder
FlockSeq bzw. FlockThr.
Der umgesetzte Algorithmus hat vereinfacht folgenden Aufbau:
6
n := Anzahl Vögel, m := Anzahl Schwärme
http://www.hpjava.org/mpiJava.html
8
http://www.cs.virginia.edu/~ajf2j/jpvm.html
7
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 12 von 98
FOR each flock
FOR each bird in flock
COMPUTE forces
STORE forces
END FOR
FOR each bird in flock
UPDATE bird
END FOR
END FOR
Wie im Pseudocode abzulesen ist, wurde auch bei der sequentiellen Implementierung die
Aufteilung des Algorithmus in zwei Teile übernommen. Dadurch sind die beiden Varianten
besser vergleichbar und die Implementierung wurde vereinfacht.
Angestoßen wird der dargestellte Ablauf in der Klasse FlockManagerSeq. Zu diesem Zweck
erweitert diese die Klasse Behavior der Java3D-Biliothek. Diese Vorgehensweise wurde in
Anlehnung an eine Umsetzung des Modells von Andrew Davison angewendet [3]. Behavior
ermöglicht es auf bestimmte Ereignisse im Ablauf der Animation zu reagieren und diese dadurch
zu beeinflussen. Klassen die Behavior erweitern müssen die Methoden initialize() und
processStimulus() überschreiben. Die Methode initialize() legt das erste Ereignis fest über das
die Anwendung informiert wird. Im Falle der Klasse FlockManagerSeq ist dies der Ablauf einer
in der Anwendung festgelegten Zeit. Ist diese Zeit verstrichen, wird die Methode
processStimulus() automatisch aufgerufen. Hier können nun Veränderungen an der Animation
vorgenommen werden die anschließend dargestellt werden. Bei der entwickelten Anwendung ist
dies der oben dargestellte Algorithmus zur Berechnung der Vogelbewegung. Damit dieser
Ablauf nicht schon nach dem ersten Ereignis unterbrochen wird, wird in der Methode
processStimulus() immer wieder das nächste Ereignis festgelegt welches den Aufruf zur Folge
haben soll. Dies ist hier die Darstellung eines Bildes der Animation. Die Simulationsdaten
werden also nach jedem dargestellten Bild aktualisiert. Bevor dies jedoch alles beginnt werden
im Konstuktor der Klasse die einzelnen Vogelschwärme erstellt und in einer Liste vom Typ
FlockList abgelegt. Diese erzeugen wiederum die benötigte Anzahl an Vögeln als Objekte vom
Typ Bird die ebenfalls in einer Liste vom Typ BirdList gespeichert werden. Jedes Mal wenn nun
die Methode processStimulus() durchlaufen wird werden, wie im Pseudocode dargestellt, alle
Schwärme zur Aktualisierung ihrer Vögel aufgefordert. Dies geschieht durch den Aufruf der
Methode updateFlock(). Diese berechnet für jeden einzelnen Vogel die nötigen Kräfte und
speichert das Ergebnis als Vektor im Vogel. Die Überprüfung ob ein Vogel ein Nachbar ist wird
beim Berechnen der Kräfte durch den Aufruf der Methode isNeighbor() der Klasse Bird
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 13 von 98
durchgeführt. Die Kräfte selbst werden durch die Methoden seperation(), cohesion() und
alignment() in der Klasse FlockSeq bestimmt. Wurden alle Berechnungen beendet, folgt die
Aktualisierung der Position, Richtung und Geschwindigkeit der Vögel durch den Aufruf der
Methode update(). Mit diesem Schritt endet der Durchlauf des Algorithmus. Auf Basis der
aktualisierten Daten wird nun ein neues Bild gezeichnet und der Ablauf beginnt von vorn. Einen
Überblick über die am sequentiellen Ablauf beteiligten Klassen und deren für den Algorithmus
relevante Methoden und Attribute bietet das folgende Klassendiagramm (Abb. 3.3).
Abbildung 3.3: Klassen der sequentiellen Implementierung
3.2.2 Parallele Implementierung
Da für die sequentielle Implementierung bereits eine Aufteilung der Vögel in mehrere Schwärme
durchgeführt wurde, bot es sich an für die Parallelisierung jeweils einen Thread pro Schwarm
einzusetzen. Dies erforderte nur geringfügige Änderungen am bestehenden Quellcode. Es
wurden die beiden Klassen FlockManagerThr und FlockThr erstellt und Anpassungen in den
Klassen AniPanel, AppSetup, FlockList und MainFrame vorgenommen. Diese sind jedoch für
das Verständnis der parallelen Implementierung nicht wichtig und werden deshalb hier nicht
besprochen. Falls erforderlich können die Anpassungen im Quellcode nachvollzogen werden.
Die eigentliche Erzeugung der Parallelität geschieht in den beiden neuen Klassen
FlockManagerThr und FlockThr. Die Klasse FlockThr implementiert die Schnittstelle Runnable
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 14 von 98
und ermöglicht dadurch die Ausführung des Schwarms als eigenständigen Thread. Eine
Erweiterung der Klasse Thread war nicht möglich, da die Klasse FlockThr bereits AbstractFlock
erweitert und Java die Mehrfachvererbung nicht unterstützt.
Der so erzeugte Thread führt folgenden Ablauf aus:
WHILE true
FOR each bird in flock
COMPUTE forces
STORE forces
END FOR
FOR each bird in flock
UPDATE bird
END FOR
SIGNAL flockManager
WAIT
END WHILE
Die Berechnung erfolgt analog zur sequentiellen Implementierung. Neu sind lediglich die äußere
Endlosschleife und die Verwendung der Methoden signal() und wait(). Die Klasse
FlockManagerThr überschreibt genau wie die sequentielle Variante die Methode
processStimulus(). Diese führt folgenden Ablauf aus:
FOR each flock
SIGNAL flock
END FOR
FOR each flock
WAIT
END FOR
Die Methode wait() stammt aus der Klasse Object und bewirkt, dass der aufrufende Thread
solange blockiert wird, bis die Methode notify() oder notifyAll() des Objekts aufgerufen wird. Sie
wird hier benutzt um einerseits den durch die Klasse FlockThr erzeugten Thread solange zu
blockieren bis eine Berechnung durchgeführt werden soll und um in der Klasse
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 15 von 98
FlockManagerThr auf das Ende aller Berechnungen zu warten. Da die Methode notify() nicht
von einem anderen Thread aus direkt aufgerufen werden kann wurde der Aufruf durch die
öffentliche Methode signal() beider Klassen gekapselt.
Im Folgenden der entsprechende Auszug aus der Klasse FlockManagerThr:
public synchronized void processStimulus (Enumeration arg0)
{
…
/* Berechnung fuer jeden Schwarm starten
for (int i = 0; i < flocks.size (); i++)
{
((FlockThr) flocks.get (i)).signal ();
};
/* Warten bis alle Schwaerme mit der Berechnung fertig sind
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
};
…
}
public synchronized void signal ()
{
sigCount++;
/* Warten bis alle Threads mit der Berechnung fertig sind
if (sigCount == AppSetup.flock_count)
{
sigCount = 0;
this.notify ();
};
}
Holger Rohde
*/
*/
*/
WS 2005/2006
Seite 16 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Der zugehörige Ablauf aus der Klasse FlockThr:
public synchronized void run ()
{
while (true)
{
Bird b = null;
/* Thread nicht beenden
*/
for (int i = 0; i < birds.size (); i++)
{
…
/* Kraefte berechnen und zwischenspeichern
*/
b.addForce (seperation (b));
b.addForce (cohesion (b));
b.addForce (alignment (b));
…
};
/* Vogeldaten anhand der berechneten Kräfte aktualisieren
*/
for (int i = 0; i < birds.size (); i++)
{
b = birds.getBird (i);
b.update (parameter);
};
manager.signal ();
/* Ende der Berechnung melden */
/* Warten bis zum naechsten Durchlauf
*/
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
};
}
}
public synchronized void signal ()
{
this.notify ();
}
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 17 von 98
Der Aufbau der parallelen Variante ist in folgendem Klassendiagramm verdeutlicht (Abb. 3.4).
Abbildung 3.4: Klassen der parallelen Implementierung (Nur die Klassen FlockManagerThr und
FlockThr sind hier neu)
3.3 Programmoberfläche
Zur Steuerung der Simulation und als Container für die Animation wurde eine einfache SwingOberfläche entwickelt. Zentraler Punkt dieser Oberfläche ist die Klasse MainFrame. Diese
enthält nicht nur alle anderen Komponenten sondern auch die Methode main() und ist somit
Startpunkt der Anwendung. Erzeugt wird je eine Instanz der Klassen AniPanel, ControlPanel,
InfoPanel, FrameMenu und Messages. Die Klassen AniPanel, ControlPanel und InfoPanel
enthalten die einzelnen Komponenten des Hauptfensters. Die innere Klasse FrameMenu
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 18 von 98
realisiert das Menü der Anwendung über das einige bereits in der Benutzerdokumentation
besprochene Einstellungen vorgenommen werden können. Eine gesonderte Rolle nimmt die
Klasse Messages ein. Über diese wurde die Internationalisierung der Anwendung realisiert. Alle
Beschriftungen und Namen der Anwendung werden aus separaten Dateien anhand eines
Schlüssels ausgelesen. Dabei wird immer automatisch die zum aktuellen Standort passende
Internationalisierungsdatei gewählt. Im Umfang der Anwendung ist eine solche Datei für die
Sprachen Deutsch und Englisch enthalten. Bei Bedarf kann der Standort und damit auch die
Sprache in der Klasse AppSetup geändert werden. Die Klasse ControlPanel enthält die in der
Benutzerdokumentation angesprochnen Schieberegler zur Steuerung der Simulationsparameter.
Die an deren Erzeugung beteiligten Klassen wurden in einem Diagramm zusammengefasst (Abb.
3.6). Die Darstellung der Messwerte des Algorithmus wird in der Klasse InfoPanel durchgeführt.
Sie enthält lediglich einige Felder zur Ausgabe der Werte und eine Methode um diese zu
aktualisieren (Abb. 3.8). Die letzte Klasse am Aufbau der Oberfläche beteiligte Klasse ist
AniPanel. Dort wird die Animation des Schwarmverhaltens aufgebaut und in einen Container
verpackt. Der Gesamtaufbau der Oberfläche wurde zur Verdeutlichung wieder in einem
Klassendiagramm dargestellt (Abb. 3.5).
Abbildung 3.5: Klassen für die Programmoberfläche
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 19 von 98
Abbildung 3.6: Klassen der unteren Steuerelemente
3.4 Animation
Die Zentrale Klasse der Java3D-Animation ist AniPanel. Dort werden die einzelnen für den
Aufbau und Ablauf der Animation benötigten Komponenten erzeugt und zu einem Szenengraph
zusammengesetzt. Diese sind in Abbildung 3.7 dargestellt. Als Quelle für die benötigten
Kenntnisse diente ein Tutorial von Sun [5] und ein weiteres Tutorial von Christopher Schnell
und Sascha Strasser [6].
3.4.1 Licht
Die Lichtquellen der Anwendung wurden in der Klasse GlobalLight platziert. Aufgrund der
einfachen Darstellung des Schwarmverhaltens beschränkt sich das Licht auf eine Quelle für
ambientes Licht und eine weitere Quelle für direktionales Licht. Diese werden ohne weitere
Anpassungen über den Standard-Konstruktor erzeugt. Lediglich der Einflussbereich des Lichts
wurde so weit ausgedehnt das dieses die komplette Welt beeinflusst.
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 20 von 98
import javax.media.j3d.AmbientLight;
import javax.media.j3d.BoundingBox;
import javax.media.j3d.DirectionalLight;
…
DirectionalLight directional = new DirectionalLight ();
AmbientLight ambient = new AmbientLight ();
BoundingBox bounds = new BoundingBox ();
/* Licht wirkt auf jedes Objekt in diesem Bereich
bounds.setLower (-10.0 ,-10.0, -10.0);
bounds.setUpper (10.0 , 10.0, 10.0);
*/
directional.setInfluencingBounds (bounds);
ambient.setInfluencingBounds (bounds);
…
Da in Java3D nur Objekte mit einen festgelegtem Oberflächenmaterial auf Lichtquellen
reagieren, beeinflusst das verwendete Licht nur das Escheinungsbild der Vögel. Alle anderen
Objekte besitze eine festgelegte Farbe.
3.4.2 Umgebung
Die Umgebung in der sich die Vögel befinden, wird in der Klasse World erzeugt. Sie besteht aus
einem Boden der durch einen Quader dargestellt wird und den Begrenzungen der Welt. Diese
werden ebenfalls durch einen Quader dargestellt, dessen Polygone aber nur als Linien zu sehen
sind. Zusätzlich zur Visualisierung der Grenzen besitzt die Welt eine Instanz der Java3D-Klasse
BoundingBox. Dieses in der Animation nicht sichtbare Objekt besitzt die gleiche Größe wie der
zur Darstellung der Grenzen verwendete Quader und bietet über die Methode intersect() die
Möglichkeit eine Überschneidung des Objekts mit anderen Objekten vom Typ BoundingBox
oder BoundingSphere zu erkennen. Es wird dadurch möglich festzustellen ob sich die Vögel
innerhalb der Welt befinden oder im Begriff sind davon zu fliegen. Die Vögel haben eine Instanz
der Klasse BoundingSphere. Diese Kugel umgibt jeden Vogel und ist ebenfalls nicht sichtbar. In
den Klassen FlockSeq und FlockThr wird zu Beginn jeder Iteration des Algorithmus geprüft ob
sich der Vogel außerhalb der Welt befindet. Ist dies der Fall werden nicht die für das
Schwarmverhalten erforderlichen Kräfte berechnet, sondern eine Kraft bestimmt die den Vogel
zurück in die Welt zwingt.
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 21 von 98
Hier der entsprechende Auszug aus der Klasse FlockSeq:
public void updateFlock ()
{
Bird b = null;
for (int i = 0; i < birds.size (); i++)
{
b = birds.getBird (i);
/*
* der Vogel muss umkehren wenn er die Begrenzung der Welt
* erreicht hat
*/
if (!b.getBs ().intersect (world.getBs ()))
{
Vector3f turn = new Vector3f (-b.getPosition ().x,
-b.getPosition ().y, -b.getPosition ().z);
b.addForce (turn);
…
}
else
{
/* Kraefte berechnen und zwischenspeichern
…
};
*/
};
…
}
3.4.3 Vögel
Die Darstellung der Vögel wird in den Klassen Bird und BirdModel realisiert. Die Klasse Bird
enthält neben den für die Simulation benötigten Methoden und Variablen eine Instanz der Klasse
BoundingSphere, die wie bereits im Zusammenhang mit der Umgebung erklärt dazu verwendet
wird, den Vogel innerhalb der Welt fest zu halten. Analog zur Welt besitzt auch der Vogel einen
Quader der dessen Grenzen visualisiert. Über diesen Quader wird auch angezeigt ob ein Vogel
gerade von den Grenzen der Welt zurückgeworfen wird (Quader ist rot), einem Hindernis
ausweicht (Quader ist gelb) oder normal innerhalb der Welt fliegt (Quader ist weiß). Die
eigentliche Darstellung des Vogels enthält die Klasse BirdModel. in Form eines um 90 Grad
gedrehten Kegels. Durch diese Trennung der Darstellung und der eigentlichen Eigenschaften
sollte es möglich werden, das Modell des Vogels jederzeit unkompliziert austauschen zu können.
Auch die Verwendung verschiedener Modelle für zum Beispiel verschiedene Vogelarten war
angedacht. Da eine Erweiterung der Darstellung im Rahmen des Projekts aber nicht mehr
möglich war, kam es nicht dazu.
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 22 von 98
3.4.4 Hindernisvermeidung
Als Hindernisse wurden drei Zylinder in der Welt platziert. Die Klasse Obstacle realisiert jeweils
einen solchen Zylinder. Das Umfliegen basiert auf dem gleichen Konzept durch das die Vögel in
der Welt gehalten werden. Jedes Hindernis besitzt eine Instanz der Klasse BoundingBox. Dieser
Quader umgibt den Zylinder wobei er etwas breiter und tiefer als der Zylinder selbst ist. Dies soll
den Vögeln etwas Zeit verschaffen um ein Ausweichmanöver durchzuführen bevor sie auf den
Zylinder auftreffen. Die Kollisionsüberprüfung wird für die Hindernisse ebenfalls in den Klassen
FlockSeq und FlockThr durchgeführt. Genauso wie bei den Weltgrenzen wird hier bei
Überschneidung der Grenzen des Vogels mit denen eines Hindernis eine Kraft bestimmt die
denn Vogel vom Hindernis wegführen soll. Dies funktioniert in der aktuellen Version der
Anwendung aber leider nicht in jedem Fall. Unter bestimmten Umständen fliegen die Vögel
durch die Hindernisse hindurch. Für eine weitere Betrachtung dieses Problems stand keine Zeit
mehr zur Verfügung.
Abbildung 3.7: Struktur der Animation
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 23 von 98
3.5 Leistungsvergleich
Da eine Implementierung verschiedener Varianten eines Algorithmus ohne einen entsprechenden
Vergleich wenig Sinn macht, wurde in das Programm eine Leistungsmessung integriert. Diese
ermöglicht die Bestimmung der Rechenzeit des Algorithmus und somit den Vergleich der
sequentiellen und parallelen Variante.
Die Leistungsmessung wurde auf Basis der freien Bibliothek JAMon9 realisiert. Diese ist zwar
eigentlich für den Einsatz im J2EE-Umfeld gedacht, eignet sich aber auch gut für Zeitmessungen
in anderen Anwendungen. Lediglich die von der Bibliothek gelieferten Ergebnisse mussten an
die Anforderungen des Programms angepasst werde. Zu diesem Zweck wurde die Klasse Timer
erstellt, die den Zugriff auf die Daten und Methoden der Bibliothek kapselt. Da die Ergebnisse
der Zeitmessung nur als eine Zeichenkette zur Verfügung stehen war es notwendig diese zu
zerlegen. Zu diesem Zweck wurde die private Methode getTokens() implementiert, die bei jedem
Aufruf der Methode stop() die erforderlichen Daten aus der Zeichenkette extrahiert und die
Variablen der Klasse aktualisiert. Die dadurch auftretende Leistungsminderung des Programms
wurde in Kauf genommen, da es nicht Ziel der Arbeit war eine besonders effiziente Simulation
zu entwickeln. In diesem Fall hätte die Zeitmessung anders realisiert werden müssen.
Die eigentliche Messung erfolgt in den Klassen FlockManagerSeq und FlockManagerThr. Diese
nutzen eine Instanz der Klasse Timer und starten die Messung jeweils vor Beginn der
Berechnung durch den Aufruf der Methode start() und stoppen sie nach dem Beenden durch den
Aufruf der Methode stop() des Timer-Objekts. Nach dem Stoppen der Messung sorgen diese
Klassen auch für die Aktualisierung der Messwerte in der Programmoberfläche. Befindet sich
das Programm im Testmodus werden die Ergebnisse nach dem Durchlaufen aller Iterationen
durch die Methode print() des Timer-Objekts auf der Konsole ausgegeben und das Programm
wird beendet.
9
http://jamonapi.com/
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 24 von 98
In der Klasse FlockManagerSeq sieht dies folgendermaßen aus:
public void processStimulus (Enumeration arg0)
{
timer.start ();
/* Zeitmessung starten
/* Berechnung fuer alle Schwaerme durchfuehren
…
timer.stop ();
/* Zeitmessung stoppen
info.updateTime (timer);
/* Infopanel aktualisieren
/* Im Testmodus die Iterationen zaehlen
if (AppSetup.benchmark == true)
{
iterations++;
};
/* Im Testmodus nach der eingestellten Anzahl Iterationen beenden
if (iterations < AppSetup.BENCH_ITERATIONS)
{
…
}
else
{
timer.print ();
/* Messergebnisse ausgeben
System.exit (0);
};
*/
*/
*/
*/
*/
*/
*/
Zur Verdeutlichung der Zusammenhänge wurden die an der Leistungsmessung beteiligten
Klassen und ihre Beziehungen in einem Diagramm zusammengefasst (Abb. 3.8).
Abbildung 3.8: An der Leistungsmessung beteiligte Klassen
Holger Rohde
WS 2005/2006
Seite 25 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Die sequentielle und parallele Variante wurden auf verschiedenen Rechnern gegenübergestellt.
Diese Aufgabe wurde mit Skripten10 automatisiert die das Programm mit den jeweiligen
Parametern aufrufen und das Ergebnis in eine Datei umleiten. Die so gewonnen Ergebnisse
sollen im Folgenden vorgestellt werden.
Der erste Test erfolgte auf einem Einprozessorsystem (Abb. 3.9). Wie nicht anders zu erwarten
war, zeigte sich, dass die parallele Variante hier keinen Boden gut machen konnte. Sie war sogar
etwas langsamer, da zusätzlich zur eigentlichen Berechnung Wechsel zwischen den einzelnen
Threads durchgeführt werden müssen. Mit zunehmenden Rechenzeiten verstärkte sich dieser
Effekt.
Athlon XP 2400+ / Windows XP / 250 Iterationen / 3 Schwärme
200000
180000
160000
Gesamtzeit (ms)
140000
120000
sequentiell
100000
parallel
80000
60000
40000
20000
0
10
20
40
sequentiell
311
597
1.486
4.049 12.670 42.858 160.263
80
160
320
640
parallel
482
753
2.303
5.398 15.517 52.982 187.477
Vögel pro Schwarm
Abbildung 3.9: Einprozessorsystems
Anders verlief der Test auf einem System mit 2 Prozessoren (Abb. 3.10). Auf diesem war die
parallele Variante insbesondere für hohe Vogelzahlen deutlich schneller. Erstaunlich war der
Unterschied zum Einprozessorsystem. Obwohl beide Systeme pro Prozessor 2Ghz besitzen
benötigte das Einprozessorsystem erheblich weniger Zeit für die Berechnungen. Sogar die
parallele Variante war auf dem Doppelprozessorsystem langsamer. Woran dies lag konnte
jedoch nicht festgestellt werden.
10
benchmark.bat und benchmark.sh im Projektverzeichnis
Holger Rohde
WS 2005/2006
Seite 26 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Dual Xeon 2 Ghz / Windows XP / 250 Iterationen / 3 Schwärme
600000
500000
Gesamtzeit (ms)
400000
sequentiell
300000
parallel
200000
100000
0
10
20
40
80
160
320
640
sequentiell
422
1.131
2.574 10.706 35.725 127.034 488.311
parallel
559
1.066
2.206
7.052 19.206 62.973 227.423
Vögel pro Schwarm
Abbildung 3.10: Doppelprozessorsystems
Als letztes wurde die Simulation auf einem System mit vier Prozessoren getestet (Abb. 3.11).
Die Ergebnisse waren hier denen des Doppelprozessorsystems sehr ähnlich. Die parallele
Variante benötigte im Durchschnitt wieder ca. die hälfte der Zeit. Trotz Verdopplung der
Prozessorzahl konnte also im Rahmen des Tests keine weitere Steigerung erzielt werden.
Holger Rohde
WS 2005/2006
Seite 27 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Sun Fire V480 / Solaris / 250 Iterationen / 3 Schwärme
350000
300000
Gesamtzeit (ms)
250000
200000
sequentiell
parallel
150000
100000
50000
0
10
20
40
80
160
320
640
sequentiell
939
1.446
2.750
6.584 20.497 70.832 295.975
parallel
795
1.106
1.999
3.981 10.833 35.401 131.877
Vögel pro Schwarm
Abbildung 3.11: System mit 4 Prozessoren
4 Fazit
Die für das Projekt festgesetzten Ziele wurden alle erreicht. Das verwendete Verfahren wurde
erläutert und dessen Parallelisierbarkeit betrachtet. Darauf basierend konnten eine sequentielle
und eine parallele Umsetzung der Simulation realisiert und bezüglich der Leistungsfähigkeit
verglichen werden. Auch die Visualisierung der Simulation mit Java3D und die Steuerung der
Simulationsparameter konnten umgesetzt werden. Von den optionalen Zielen wurde die
Integration der Hindernisse teilweise umgesetzt. Leider stand keine Zeit mehr zur Verfügung um
die in diesem Zusammenhang noch bestehenden Probleme zu lösen. Die Verbesserung der
Visualisierung bezüglich der Vögel und deren Umgebung musste leider komplett gestrichen
werden.
5 Anhang
5.1 Quellenverzeichnis
[1]
Boid-Modell von Craig Reynolds
http://www.cs.toronto.edu/~dt/siggraph97-course/cwr87/
[2]
Boid-Modell von Craig Reynolds
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 28 von 98
http://www.red3d.com/cwr/boids/
[3]
Java Implementierung des Boid Modell von Andrew Davison
http://fivedots.coe.psu.ac.th/~ad/jg/ch13/index.html
[4]
Ausarbeitung zum Boid-Modell von Olaf Schnapauff
http://www.sc.cs.tu-bs.de/pare/projekte/olaf/papers/voegel.ps.gz
[5]
Sun Java3D Tutorial
http://java.sun.com/developer/onlineTraining/java3d/
[6]
Java3D Tutorial von Schnell und Strasser
http://java3d.j3d.org/downloads/Java3D_schnell_tutorial.pdf
5.2 Quellcode
5.2.1 Packet ani
5.2.1.1 AbstractFlock.java
/*
* Klasse(n):
AbstractFlock
* Bemerkungen: *
* Datei:
AbstractFlock.java
Autor:
Holger Rohde
* Datum:
03.11.05
Version: 0.6
*
* Historie:
*
* 26.12.05 - Farbe fuer Signalisierung des Auftreffen auf Hindernisse
*
als Konstante hinzugefuegt.
* 25.12.05 - Methode "protected void switchBirdBounds ()" zum Ein- und
*
Ausschalten der Visualisierung der Vogelgrenzen
*
hinzugefuegt.
* 17.12.05 - Farbe fuer Signalisierung des Auftreffen auf Weltgrenzen
*
als Konstante hinzugefuegt.
* 08.12.05 - Methoden "protected Vector3f getFlockPosition ()" und
*
"protected Vector3f getFlockDirection ()" hinzugefuegt
*
um neue Voegel in die Mitte des Schwarms zu setzen. /
*
Methode "protected void updateParameter
*
(ParameterSet updParamter)" entsprechend angepasst.
* 07.12.05 - ParameterSet und Methode "protected void updateParameter
*
(ParameterSet updParamter)" zur Steuerung der Parameter
*
des Algorithmus hinzugefuegt.
*/
package ani;
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
import
import
import
import
import
Seite 29 von 98
java.util.Random;
javax.media.j3d.BranchGroup;
javax.media.j3d.ColoringAttributes;
javax.vecmath.Color3f;
javax.vecmath.Vector3f;
import util.BirdList;
import util.ParameterSet;
/*
* Realisierung eines Vogelschwarms. Dieser verwaltet eine Liste seiner
* Voegel, und berechnet die Kraefte anhand einstellbarer Parameter.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* world
- Referenz auf die Instanz der Klasse World
* birdColor - Die Farbe der Voegel dieses Schwarms
* birds
- Die Liste mit allen Voegeln des Schwarms
* parameter - Die aktuell gueltigen Parameter fuer die Berechnungen
*
* oeffentliche Methoden:
* ---------------------*
* keine
*
* private Methoden:
* ---------------------*
* seperation
* cohesion
* alignment
* updateParameter
* getFlockPostion
* getFlockDirection
* switchBirdBounds
* randomVector
*
*/
public abstract class AbstractFlock extends BranchGroup
{
protected static ColoringAttributes WORLD_HIT_CA =
new ColoringAttributes ( new Color3f (0.9F, 0.0F, 0.0F),
ColoringAttributes.NICEST);
protected static ColoringAttributes OBS_HIT_CA =
new ColoringAttributes (new Color3f (0.9F, 0.9F, 0.0F),
ColoringAttributes.NICEST);
protected
protected
protected
protected
Holger Rohde
World world = null;
Color3f birdColor = null;
BirdList birds = new BirdList ();
ParameterSet parameter = new ParameterSet ();
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 30 von 98
protected AbstractFlock (Color3f birdColor, World world, int range)
{
this.world = world;
this.birdColor = birdColor;
this.setCapability (BranchGroup.ALLOW_CHILDREN_WRITE);
this.setCapability (BranchGroup.ALLOW_CHILDREN_EXTEND);
for (int i = 0; i < parameter.getBirdCount (); i++)
{
Bird b = new Bird (birdColor, randomVector (range),
randomVector (range));
birds.add (b);
this.addChild (b);
};
}
/*
* Berechnung der Kraft "seperation". Fuer alle Nachbarvoegel wird
* der Vektor zwischen der Position des Vogel und der des Nachbarn
* bestimmt und auf das Ergebnis addiert. Vor dem zurueckgeben wird
* das Ergenbnis gemittelt und anhand der in der Programmoberflaeche
* eingestellten Staerke gewichtet.
*
* Eingabeparameter: Bird b
* Ausgabeparameter: Vector3f result
* Fehlerausgaenge:
*/
protected Vector3f seperation (Bird b)
{
int neighbors = 0;
Bird otherBird = null;
Vector3f result = new Vector3f ();
Vector3f difference = new Vector3f ();
for (int i = 0; i < birds.size (); i++)
{
otherBird = birds.getBird (i);
/* nur fuer Nachbarn durchfuehren und sich selbst ueberspringen
if (!b.equals (otherBird)
&& b.isNeighbor (otherBird, parameter.getSepDistance (),
parameter.getSepAngleCos ()))
{
neighbors++;
difference.set (b.getPosition ());
/* Vektor von der eigenen Position zum Nachbar bestimmen
difference.sub (otherBird.getPosition ());
/* Vektor auf Ergebnis addieren */
result.add (difference);
}
;
}
;
if (neighbors > 0)
{
result.scale (1.0F / neighbors); /* Mittel bestimmen
result.normalize ();
/* Kraft gewichten
result.scale (parameter.getSepStrength ());
}
;
Holger Rohde
*/
*/
*/
*/
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 31 von 98
return result;
}
/*
* Berechnung der Kraft "cohesion". Es werden alle Positionen der
* Nachbarvoegel aufaddiert und vor dem Zurueckgeben gemittelt und
* gewichtet.
*
* Eingabeparameter: Bird b
* Ausgabeparameter: Vector3f result
* Fehlerausgaenge:
*/
protected Vector3f cohesion (Bird b)
{
int neighbors = 0;
Bird otherBird = null;
Vector3f result = new Vector3f ();
for (int i = 0; i < birds.size (); i++)
{
otherBird = birds.getBird (i);
/* nur fuer Nachbarn durchfuehren und sich selbst ueberspringen
if (!b.equals (otherBird)
&& b.isNeighbor (otherBird, parameter.getCohDistance (),
parameter.getCohAngleCos ()))
{
neighbors++;
/* Die einzelnen Positionsvektoren aufaddieren
result.add (otherBird.getPosition ());
};
};
if (neighbors > 0)
{
result.scale (1.0F / neighbors); /* Mittel bestimmen
result.sub (b.getPosition ());
/* Kraft zum Mittelpunkt
result.normalize ();
/* Kraft gewichten
result.scale (parameter.getCohStrength ());
};
return result;
*/
*/
*/
*/
*/
}
/*
* Berechnung der Kraft "alignment". Es werden alle Richtungen der
* Nachbarvoegel aufaddiert und vor dem Zurueckgeben gemittelt und
* gewichtet.
*
* Eingabeparameter: Bird b
* Ausgabeparameter: Vector3f result
* Fehlerausgaenge:
*/
protected Vector3f alignment (Bird b)
{
int neighbors = 0;
Bird otherBird = null;
Vector3f result = new Vector3f ();
for (int i = 0; i < birds.size (); i++)
{
otherBird = birds.getBird (i);
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 32 von 98
/* nur fuer Nachbarn durchfuehren und sich selbst ueberspringen */
if (!b.equals (otherBird)
&& b.isNeighbor (otherBird, parameter.getAlignDistance (),
parameter.getAlignAngleCos ()))
{
neighbors++;
/* Die einzelnen Richtungsvektoren aufaddieren
*/
result.add (otherBird.getDirection ());
};
};
if (neighbors > 0)
{
result.scale (1.0F / neighbors); /* Mittel bestimmen
result.normalize ();
/* Kraft gewichten
result.scale (parameter.getAliStrength ());
};
return result;
*/
*/
}
/*
* Einstellungen aus dem Kontrollpanel uebernehmen.
*
* Eingabeparameter: ParameterSet updParamter
* Ausgabeparameter: * Fehlerausgaenge:
CloneNotSupportedException
*/
protected void updateParameter (ParameterSet updParamter)
{
int diff = updParamter.getBirdCount () - parameter.getBirdCount ();
if (diff > 0)
{
for (int i = 0; i < diff; i++)
{
/* neuen Vogel in die Mitte des Schwarms setzen
Bird b = new Bird (birdColor, getFlockPosition (),
getFlockDirection ());
*/
birds.add (b);
this.addChild (b);
};
}
else if (diff < 0)
{
for (int i = 0; i < -diff; i++)
{
/* letzen Vogel in der Liste entfernen
*/
this.removeChild ((BranchGroup) birds.get (birds.size () - 1));
birds.remove (birds.size () - 1);
};
};
/* lokale Parameter mit neuen Parametern ueberschreiben
*/
try
{
parameter = updParamter;
parameter = (ParameterSet) updParamter.clone ();
}
catch (CloneNotSupportedException ce)
{
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 33 von 98
ce.printStackTrace ();
};
}
/*
* Aktuelle mittlere Position des Schwarms bestimmen.
*
* Eingabeparameter: * Ausgabeparameter: Vector3f result
* Fehlerausgaenge:
*/
protected Vector3f getFlockPosition ()
{
Vector3f result = new Vector3f ();
for (int i = 0; i < birds.size (); i++)
{
result.add (birds.getBird (i).getPosition ());
};
result.scale (1.0F / birds.size ());
result.normalize ();
return result;
}
/*
* Aktuelle mittlere Richtung des Schwarms bestimmen.
*
* Eingabeparameter: * Ausgabeparameter: Vector3f result
* Fehlerausgaenge:
*/
private Vector3f getFlockDirection ()
{
Vector3f result = new Vector3f ();
for (int i = 0; i < birds.size (); i++)
{
result.add (birds.getBird (i).getDirection ());
};
result.scale (1.0F / birds.size ());
result.normalize ();
return result;
}
/*
* Aus- oder Einschalten der Visualisierung der Grenzen fuer alle
* Voegel.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
protected void switchBirdBounds ()
{
for (int i = 0; i < birds.size (); i++)
{
birds.getBird (i).switchBounds ();
};
}
Holger Rohde
WS 2005/2006
Seite 34 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
/*
* Zufallsvektor in verschiedenen Quadranten der Koordinatensystems
* bestimmen.
*
* Eingabeparameter: int range
* Ausgabeparameter: Vector3f result
* Fehlerausgaenge:
*/
private Vector3f randomVector (int range)
{
Random random = new Random ();
Vector3f result = new Vector3f (random.nextFloat () * 1.3F,
random.nextFloat () * 1.3F, random.nextFloat () * 1.3F);
switch (range)
{
case 0:
break;
case 1:
result.x =
result.y =
break;
case 2:
result.x =
result.z =
break;
case 3:
result.y =
result.z =
break;
default:
break;
};
return result;
/* Auswahl des Quadrant
*/
-result.x;
-result.y;
-result.x;
-result.z;
-result.y;
-result.z;
}
}
5.2.1.2 AbstractFlockManager.java
/*
* Klasse(n):
AbstractFlockManager
* Bemerkungen: *
* Datei:
AbstractFlockManager.java
Autor:
Holger Rohde
* Datum:
03.11.05
Version: 0.5
*
* Historie:
*
* 26.12.05 - Variable "iterations" fuer den Testmodus hinzugefuegt.
* 25.12.05 - Methode "protected void switchBirdBounds ()" hinzugefuegt.
* 18.12.05 - Objekt "timer" fuer die Zeitmessung hinzugefuegt. /
*
Referenz auf InfoPanel hinzugefuegt.
* 07.12.05 - Methode "protected void updateFlocks
*
(ParameterSet parameter)" hinzugefuegt.
*
*/
package ani;
import java.util.Enumeration;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 35 von 98
import javax.media.j3d.WakeupOnElapsedTime;
import javax.vecmath.Color3f;
import
import
import
import
import
gui.InfoPanel;
util.AppSetup;
util.FlockList;
util.ParameterSet;
util.Timer;
/*
* Klasse zur Verwaltung der Schwaerme und das Starten der Berechnung.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* iterations - Zaehervariable fuer die durchlaufenen Iterationen
* world
- Referenz auf die Instanz der Klasse World
* info
- Referenz auf die Instanz der Klasse InfoPanel
* timer
- Instanz der Klasse Timer fuer die Zeitmessung
* flocks
- Liste der Schwaerme
* flockCol
- Feld mit verschiedenen Farben fuer die Schwaerme
*
* oeffentliche Methoden:
* ---------------------*
* initialize
*
* private Methoden:
* ---------------------*
* switchBirdBounds
* updateFlocks
* processStimulus - abstract
*
*/
public abstract class AbstractFlockManager extends Behavior
{
protected long iterations = 0;
protected World world = null;
protected InfoPanel info = null;
protected Timer timer = new Timer ();
protected FlockList flocks = new FlockList ();
protected Color3f flockCol [] = {new Color3f (0.4F, 0.0F, 0.0F),
new Color3f (0.0F, 0.0F, 0.4F), new Color3f (0.0F, 0.4F, 0.0F)};
protected AbstractFlockManager (World world, InfoPanel info)
{
this.world = world;
this.info = info;
/* noetig damit ein Ereignis ausgeloest wird
this.setSchedulingBounds (new BoundingSphere ());
}
*/
/*
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 36 von 98
* Legt fest nach welchem Ereignis die Methode processStimulus das
* erste mal aufegerufen wird.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void initialize ()
{
this.wakeupOn (new WakeupOnElapsedTime (AppSetup.INIT_WAKEUP));
}
/*
* Ein- und Ausschalten der Visualisierung der Vogelgrenzen an
* die Schwaerme weiter geben.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
protected void switchBirdBounds ()
{
for (int i = 0; i < flocks.size (); i++)
{
if (this instanceof FlockManagerSeq)
{
flocks.getFlock (i).switchBirdBounds ( );
}
else if (this instanceof FlockManagerThr)
{
flocks.getFlockThr (i).switchBirdBounds ( );
};
};
}
/*
* Aktualisierte Parameter von den Kontrollen an die Schwaerme
* weiterreichen.
*
* Eingabeparameter: ParameterSet parameter
* Ausgabeparameter: * Fehlerausgaenge:
*/
protected void updateFlocks (ParameterSet parameter)
{
for (int i = 0; i < flocks.size (); i++)
{
if (this instanceof FlockManagerSeq)
{
flocks.getFlock (i).updateParameter (parameter);
}
else if (this instanceof FlockManagerThr)
{
flocks.getFlockThr (i).updateParameter (parameter);
};
};
}
public abstract void processStimulus (Enumeration arg0);
}
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 37 von 98
5.2.1.3 AniPanel.java
/*
* Klasse(n):
AniPanel
* Bemerkungen: *
* Datei:
AniPanel.java
Autor:
Holger Rohde
* Datum:
01.11.05
Version: 1.1
*
* Historie:
*
* 26.12.05 - Methode "public void switchObstacles ()" zum Ein- und
*
Ausschalten der Hindernisse aus dem Menue hinzugefuegt.
* 25.12.05 - Methode "public void switchBirdBounds ()" fuer die
*
Menuesteuerung hinzugefuegt.
* 23.12.05 - Erstellung des FlockManger abhaengig von Parameter
*
AppSetup.use_threads als FlockManagerSeq oder
*
FlockManagerThr.
* 21.12.05 - Rand um das Panel gelegt.
* 20.12.05 - Kameraposition angepasst. Methode "public void
*
"public void switchWorldBounds ()" fuer die Menuesteuerung
*
hinzugefuegt.
* 17.12.05 - Hintergrundfarbe der Animation gesetzt.
* 07.12.05 - Methode "public void updateFlockManager
*
(ParameterSet parameter)" hinzugefuegt um Aktualisierungen
*
aus dem ControlPanel an den FlockMangager weiterzuleiten.
* 18.11.05 - Licht hinzugefuegt.
* 05.11.05 - Rotieren der Animation mittels der Maus hinzugefuegt.
* 03.11.05 - Erstellung des FlockManagers hinzugefuegt.
*/
package ani;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.GraphicsConfiguration;
javax.media.j3d.Background;
javax.media.j3d.BoundingSphere;
javax.media.j3d.BranchGroup;
javax.media.j3d.Canvas3D;
javax.media.j3d.Transform3D;
javax.media.j3d.TransformGroup;
javax.swing.JPanel;
javax.swing.border.BevelBorder;
javax.vecmath.Color3f;
javax.vecmath.Point3d;
javax.vecmath.Vector3d;
com.sun.j3d.utils.behaviors.mouse.MouseRotate;
com.sun.j3d.utils.universe.SimpleUniverse;
import gui.InfoPanel;
import util.AppSetup;
import util.ParameterSet;
/*
*
*
*
*
*
*
*
*
*
Container der Java3D Animation.
oeffentliche Daten:
---------------------keine
private Daten:
----------------------
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 38 von 98
*
* serialVersionUID - Da JPanel das Interace Serializable
*
implementiert ist diese Variable notwendig (hat
*
hier aber keine weitere Funktion)
* world
- Instanz der Klasse World die die Umgebung der
*
Voegel aufbaut
* light
- Instanz der Klasse GlobalLight die der Szene
*
Lichtquelle hinzufuegt
* flockManager
- Instanz der Klasse FlockManagerSeq oder
*
FlockManagerThr zur Verwaltung der Schwaerme
* info
- Referez auf die Instanz des Infopanel
*
* oeffentliche Methoden:
* ---------------------*
* updateFlockManager
* switchBirdBounds
* switchWorldBounds
* switchObstacles
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class AniPanel extends JPanel
{
private static Color3f BG_COLOR = new Color3f (0.6F, 0.6F, 0.6F);
private
private
private
private
private
static final long serialVersionUID = 1;
World world = new World ();
GlobalLight light = new GlobalLight ();
AbstractFlockManager flockManager = null;
InfoPanel info = null;
public AniPanel (InfoPanel info)
{
this.info = info;
GraphicsConfiguration gc =
SimpleUniverse.getPreferredConfiguration ();
Canvas3D canvas = new Canvas3D (gc);
canvas.setPreferredSize(AppSetup.animationSize);
SimpleUniverse universe = new SimpleUniverse (canvas);
BranchGroup rootGroup = new BranchGroup ();
TransformGroup tg = new TransformGroup ();
/*
* Erzeugung des flockManager-Objekt fuer parallele oder
* seqeuntielle Berechnung.
*/
if (AppSetup.use_threads == true)
{
flockManager = new FlockManagerThr (world, info);
}
else
{
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 39 von 98
flockManager = new FlockManagerSeq (world, info);
};
/* Sicht auf die Szenen anpassen
Transform3D view= new Transform3D ();
view.lookAt (new Point3d (0.0, 5.0, 5.0),
new Point3d (0.0, -0.5, 0.0), new Vector3d (0.0, 1.0, 0.0));
view.invert ();
universe.getViewingPlatform().getViewPlatformTransform().
setTransform (view);
*/
Background aniBackground = new Background (BG_COLOR);
aniBackground.setApplicationBounds (new BoundingSphere ());
/* Rotieren der Szene mit der linken Maustaste
MouseRotate mouseRotate = new MouseRotate ();
mouseRotate.setTransformGroup (tg);
mouseRotate.setSchedulingBounds (new BoundingSphere ());
*/
tg.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
tg.setCapability (TransformGroup.ALLOW_TRANSFORM_READ);
this.setBorder (new BevelBorder (BevelBorder.LOWERED));
this.add (canvas);
tg.addChild (flockManager);
tg.addChild (light);
tg.addChild (world);
rootGroup.addChild (tg);
rootGroup.addChild(aniBackground);
rootGroup.addChild (mouseRotate);
rootGroup.compile();
/* optimieren des Szenengraph */
universe.addBranchGraph(rootGroup);
}
/*
* Aktuelle Parameter zur Instanz der Klasse
* FlockManagerSeq oder FlockManagerThr weiterreichen.
*
* Eingabeparameter: ParameterSet parameter
* Ausgabeparameter: * Fehlerausgaenge:
*/
public void updateFlockManager (ParameterSet parameter)
{
flockManager.updateFlocks (parameter);
}
/*
* Ein- und Auschalten Vogelbegrenzungen zur Instanz der Klasse
* FlockManagerSeq oder FlockManagerThr weiterreichen.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void switchBirdBounds ()
{
flockManager.switchBirdBounds ();
}
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 40 von 98
/*
* Ein- und Auschalten Weltbegrenzungen zur Instanz der Klasse
* World weiterreichen.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void switchWorldBounds ()
{
world.switchBounds ();
}
/*
* Ein- und Auschalten der Hindernisse zur Instanz der Klasse World
* weiterreichen.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void switchObstacles ()
{
world.switchObstacles ();
}
}
5.2.1.4 Bird.java
/*
* Klasse(n):
Bird
* Bemerkungen: *
* Datei:
Bird.java
Autor:
Holger Rohde
* Datum:
01.11.05
Version: 0.4
*
* Historie:
*
* 25.12.05 - Methode "public void switchBounds ()" zum Ein- und
*
der Anzeige der Grenzen hinzugefuegt.
* 17.12.05 - Methode "public void setBoundsColoringAttributes
*
(ColoringAttributes ca)" zum Setzen der Farbe der Grenzen
*
hinzugefuegt.
* 07.12.05 - Methode "public void update (ParameterSet parameter)" auf
*
Nutzung des ParamterSet umgestellt.
*/
package ani;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
import
import
import
import
import
import
import
import
Seite 41 von 98
javax.media.j3d.ColoringAttributes;
javax.media.j3d.PolygonAttributes;
javax.media.j3d.Transform3D;
javax.media.j3d.TransformGroup;
javax.media.j3d.TransparencyAttributes;
javax.vecmath.Color3f;
javax.vecmath.Point3d;
javax.vecmath.Vector3f;
import com.sun.j3d.utils.geometry.Box;
import util.AppSetup;
import util.ParameterSet;
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Klasse zur Nachbildung eines Vogels.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------position
direction
velocity
forces
-
birdModel
-
boundsAp
-
tg
bounds
boundsBox
boundsGroup
-
Vektor zur Speicherung der Position des Vogels
Vektor zur Speicherung der Flugrichtung des Vogels
Vektor zur Speicherung der Geschwindigkeit des Vogels
Vektor zur Zwischenspeicherung der Kraefte die auf den
Vogel wirken
ein einfaches Modell zur Darstellung des Vogels in der
Animation
Erscheinungsbild der Visualisierung der Grenzen des
Vogels
Tranformationsgruppe fuer die Bewegung des Vogels
Die imaginaeren Grenzen um den Vogel
Visualisierung der Grenzen mit einem Quader
BranchGroup fuer das Objekt boundsBox
oeffentliche Methoden:
---------------------update
isNeighbor
switchBounds
setBoundsColoringAttributes
addForce
Getter / Setter:
getPosition
getDirection
getVelocity
getBs
private Methoden:
---------------------move
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 42 von 98
*/
public class Bird extends BranchGroup
{
private Vector3f position = new Vector3f ();
private Vector3f direction = new Vector3f ();
private Vector3f velocity = new Vector3f (AppSetup.speed_def,
AppSetup.speed_def, 0.0F);
private Vector3f forces = new Vector3f ();
private
private
private
private
BirdModel birdModel = null;
Appearance boundsAp = new Appearance ();
TransformGroup tg = new TransformGroup ();
BoundingSphere bounds = new BoundingSphere ();
/*
* Nur Gruppen koennen bei laufender Animation hinzugefuegt und
* entfernt werden. Deshalb benoetigten wir eine extra Gruppe fuer
* den Grenzquader.
*/
private BranchGroup boundsGroup = new BranchGroup ();
public Bird (Color3f birdColor, Vector3f position, Vector3f direction)
{
this.direction = direction;
this.position = position;
PolygonAttributes pa = new PolygonAttributes ();
TransparencyAttributes ta = new TransparencyAttributes ();
birdModel = new BirdModel (birdColor);
Box boundsBox = new Box (AppSetup.BIRD_SIZE * 2,
AppSetup.BIRD_SIZE * 2, AppSetup.BIRD_SIZE * 2, boundsAp);
tg.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
tg.setCapability (TransformGroup.ALLOW_TRANSFORM_READ);
tg.setCapability (TransformGroup.ALLOW_CHILDREN_WRITE);
tg.setCapability (TransformGroup.ALLOW_CHILDREN_EXTEND);
boundsAp.setCapability (Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
boundsGroup.setCapability (BranchGroup.ALLOW_DETACH);
this.setCapability (BranchGroup.ALLOW_DETACH);
bounds.setRadius (AppSetup.BIRD_SIZE);
pa.setPolygonMode (PolygonAttributes.POLYGON_LINE);
ta.setTransparencyMode (TransparencyAttributes.FASTEST);
ta.setTransparency (0.7F);
boundsAp.setTransparencyAttributes (ta);
boundsAp.setPolygonAttributes (pa);
boundsBox.setAppearance (boundsAp);
tg.addChild (birdModel);
boundsGroup.addChild (boundsBox);
if (AppSetup.bird_bounds == true)
{
tg.addChild (boundsGroup);
};
this.addChild(tg);
this.move ();
}
/*
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 43 von 98
* Aktualisierung der Position, Richtung und Geschwindigkeit anhand
* der gespeicherten Kräfte.
*
* Eingabeparameter: ParameterSet parameter
* Ausgabeparameter: * Fehlerausgaenge:
*/
public void update (ParameterSet parameter)
{
if (forces.length () > parameter.getMaxForce () )
{
forces.scale (parameter.getMaxForce () / forces.length ());
};
velocity.add (forces);
if (velocity.length () > parameter.getMaxSpeed ())
{
velocity.scale (parameter.getMaxSpeed () / velocity.length ());
};
position.add (velocity);
if (velocity.length () > 0)
{
direction.set (velocity);
direction.normalize ();
};
forces.set (0.0F, 0.0F, 0.0F);
this.move ();
}
/*
* Bewegt den Vogel in der Animation zur aktuellen Position und dreht
* ihn in die Flugrichtung. Die Drehung ueber die Methode atan2
* wurde aus einer Veroeffentlichung zum Schwarmverhalten von
* Andrew Davison uebernommen
* (http://fivedots.coe.psu.ac.th/~ad/jg/ch13/index.html).
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
private void move ()
{
Transform3D move = new Transform3D ();
move.rotY (Math.atan2 (velocity.x, velocity.z));
move.setTranslation (position);
tg.setTransform (move);
/* Grenzen des Vogels auch auf neue Position setzen
*/
bounds.setCenter (new Point3d (position.x, position.y, position.z));
}
/*
*
*
*
*
*
*
*
*
*
Bestimmt ob ein Vogel Nachbar dieses Vogels ist. Dazu wird die
Distanz zwischen den beiden Voegeln ermittelt und mit dem
vorgegebenen Wert verglichen. Zur Ueberpruefung ob sich der Vogel
im Sichtwinkel befindet wird das Skalarprodukt der Flugrichtung und
des Vektors zum anderen Vogel ermittelt. Da der Betrag der
Richtungsvektoren 1 betraegt erhaelt man so den Winkel zwischen den
Vektoren.
Eingabeparameter:
Holger Rohde
Bird b
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 44 von 98
*
double distance
*
double angle
* Ausgabeparameter: boolean ret
* Fehlerausgaenge:
*/
public boolean isNeighbor (Bird b, double distance, double angle)
{
boolean ret = false;
Vector3f birdDistance = new Vector3f ();
birdDistance.set (b.getPosition ());
birdDistance.sub (position);
/* Abstand ermitteln
if (birdDistance.length () < distance)
{
birdDistance.normalize ();
/* Sichtwinkel ueberpruefen
ret = birdDistance.dot (direction) > angle;
};
return ret;
*/
*/
}
/*
* Visualisierung der Vogelbegrenzungen ein- und ausschalten.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void switchBounds ()
{
/* Grenzen werden gerade angezeigt
if (boundsGroup.isLive () == true)
{
AppSetup.bird_bounds = false;
tg.removeChild (boundsGroup);
}
else
{
AppSetup.bird_bounds = true;
tg.addChild (boundsGroup);
};
}
*/
/*
* Farbe der Visualisierung der Vogelgrenzen setzen.
*
* Eingabeparameter: ColoringAttributes ca
* Ausgabeparameter: * Fehlerausgaenge:
*/
public void setBoundsColoringAttributes (ColoringAttributes ca)
{
boundsAp.setColoringAttributes (ca);
}
/*
* Eine fuer den Vogel berechnete Kraft zwischenspeichern.
*
* Eingabeparameter: Vector3f force
* Ausgabeparameter: -
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 45 von 98
* Fehlerausgaenge:
*/
public void addForce (Vector3f force)
{
forces.add (force);
}
public Vector3f getPosition ()
{
return position;
}
public Vector3f getDirection ()
{
return direction;
}
public Vector3f getVelocity ()
{
return velocity;
}
/*
* Rueckgabe der Grenzen des Vogels zur Ueberpruefung ob er die Welt
* verlassen hat oder mit einem Hindernis kolidiert.
*
* Eingabeparameter: * Ausgabeparameter: BoundingSphere bounds
* Fehlerausgaenge:
*/
public BoundingSphere getBs ()
{
return bounds;
}
}
5.2.1.5 BirdModel.java
/*
* Klasse(n):
BirdModel
* Bemerkungen: *
* Datei:
BirdModel.java
Autor:
Holger Rohde
* Datum:
01.11.05
Version: 0.3
*
* Historie:
*
* 24.12.05 - Die bisher zur Darstellung des Vogels verwendete Kugel
*
durch einen um 90 Grad gedrehten Kegel ersetzt.
* 20.11.05 - Auf Licht reagierendes Material statt einfacher
*
Objektfarbe.
*
*/
package ani;
import javax.media.j3d.Appearance;
Holger Rohde
WS 2005/2006
Seite 46 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
import
import
import
import
import
import
javax.media.j3d.BranchGroup;
javax.media.j3d.Material;
javax.media.j3d.Transform3D;
javax.media.j3d.TransformGroup;
javax.vecmath.Color3f;
com.sun.j3d.utils.geometry.Cone;
import util.AppSetup;
/*
* Ein einfaches Modell zur Visualisierung des Vogels.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* keine
*
* oeffentliche Methoden:
* ---------------------*
* keine
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class BirdModel extends BranchGroup
{
public BirdModel (Color3f birdColor)
{
Appearance ap = new Appearance ();
Material mat = new Material ();
TransformGroup tg = new TransformGroup ();
Transform3D coneTrans = new Transform3D ();
Cone cone = new Cone (AppSetup.BIRD_SIZE,
AppSetup.BIRD_SIZE * 3, ap);
coneTrans.rotX (Math.PI / 2);
/* Drehung um 90 Grad
*/
tg.setCapability (TransformGroup.ALLOW_TRANSFORM_READ);
tg.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
tg.setTransform (coneTrans);
mat.setDiffuseColor (birdColor);
mat.setAmbientColor (birdColor);
mat.setShininess (50F);
ap.setMaterial (mat);
tg.addChild (cone);
this.addChild (tg);
}
}
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 47 von 98
5.2.1.6 FlockManagerSeq.java
/*
* Klasse(n):
FlockManagerSeq
* Bemerkungen: *
* Datei:
FlockManagerSeq.java
Autor:
Holger Rohde
* Datum:
03.11.05
Version: 0.3
*
* Historie:
*
* 26.12.05 - Beenden und Ausgabe der Messwerte im Testmodus
*
hinzugefuegt.
* 18.12.05 - Zeitmessung ergaenzt.
*
*/
package ani;
import java.util.Enumeration;
import javax.media.j3d.WakeupOnElapsedFrames;
import gui.InfoPanel;
import util.AppSetup;
/*
* Klasse erweitert AbstractFlockManager um die fuer die sequentielle
* Berechnung benoetigen Eigenschaften.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* keine
*
* oeffentliche Methoden:
* ---------------------*
* processStimulus
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class FlockManagerSeq extends AbstractFlockManager
{
public FlockManagerSeq (World world, InfoPanel info)
{
super (world, info);
for (int i = 0; i < AppSetup.flock_count; i++)
{
FlockSeq f = new FlockSeq (flockCol [i % flockCol.length], world,
i % 4);
flocks.add (f);
world.addChild (f);
Holger Rohde
WS 2005/2006
Seite 48 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
};
}
/*
* Startet nach jedem Bild der Animation eine neue Berechnung der
* Kraefte.
*
* Eingabeparameter: Enumeration arg0
* Ausgabeparameter: * Fehlerausgaenge:
InterruptedException
*/
public void processStimulus (Enumeration arg0)
{
timer.start ();
/* Zeitmessung starten
/* Berechnung fuer alle Schwaerme durchfuehren
for (int i = 0; i < flocks.size (); i++)
{
flocks.getFlock (i).updateFlock ();
};
timer.stop ();
/* Zeitmessung stoppen
info.updateTime (timer);
/* Infopanel aktualisieren
/* Im Testmodus die Iterationen zaehlen
if (AppSetup.benchmark == true)
{
iterations++;
};
/* Im Testmodus nach der eingestellten Anzahl Iterationen beenden
if (iterations < AppSetup.BENCH_ITERATIONS)
{
/* erneuter Aufruf nach Anzeige des naechsten Bilds
wakeupOn (new WakeupOnElapsedFrames (1));
}
else
{
timer.print ();
/* Messergebnisse ausgeben
System.exit (0);
};
}
*/
*/
*/
*/
*/
*/
*/
*/
}
5.2.1.7 FlockManagerThr.java
/*
* Klasse(n):
FlockManagerThr
* Bemerkungen: *
* Datei:
FlockManagerThr.java
* Datum:
23.12.05
*
* Historie:
*
* keine Aenderungen
*
*/
package ani;
Autor:
Holger Rohde
Version: 0.1
import java.util.Enumeration;
import javax.media.j3d.WakeupOnElapsedFrames;
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 49 von 98
import gui.InfoPanel;
import util.AppSetup;
/*
* Klasse erweitert AbstractFlockManager um die fuer die parallele
* Berechnung benoetigen Eigenschaften.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* sigCount - Zaehlvariable fuer Signalisierung durch Threads
*
* oeffentliche Methoden:
* ---------------------*
* processStimulus
* signal
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class FlockManagerThr extends AbstractFlockManager
{
private int sigCount = 0;
public FlockManagerThr (World world, InfoPanel info)
{
super (world, info);
for (int i = 0; i < AppSetup.flock_count; i++)
{
FlockThr f = new FlockThr (flockCol [i % flockCol.length], world,
this, i % 4);
flocks.add (f);
new Thread (f).start ();
world.addChild (f);
if (AppSetup.debug == true)
{
System.out.println ("thread " + i + " started");
};
};
}
/*
* Startet nach jedem
* Kraefte.
*
* Eingabeparameter:
* Ausgabeparameter:
* Fehlerausgaenge:
*/
Holger Rohde
Bild der Animation eine neue Berechnung der
Enumeration arg0
InterruptedException
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 50 von 98
public synchronized void processStimulus (Enumeration arg0)
{
timer.start ();
/* Zeitmessung starten
/* Berechnung fuer jeden Schwarm starten
for (int i = 0; i < flocks.size (); i++)
{
((FlockThr) flocks.get (i)).signal ();
};
/* Warten bis alle Schwaerme mit der Berechnung fertig sind
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
};
timer.stop ();
/* Zeitmessung stoppen
info.updateTime (timer);
/* Infopanel aktualisieren
/* Im Testmodus die Iterationen zaehlen
if (AppSetup.benchmark == true)
{
iterations++;
};
/* Im Testmodus nach der eingestellten Anzahl Iterationen beenden
if (iterations < AppSetup.BENCH_ITERATIONS)
{
/* erneuter Aufruf nach Anzeige des naechsten Bilds
wakeupOn (new WakeupOnElapsedFrames (1));
}
else
{
timer.print ();
/* Messergebnisse ausgeben
System.exit (0);
};
}
*/
*/
*/
*/
*/
*/
*/
*/
*/
/*
* Kapselt den Aufruf der Methode notify(). Ermoeglicht deren Aufruf
* durch einen anderen Thread.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public synchronized void signal ()
{
sigCount++;
/* Warten bis alle Threads mit der Berechnung fertig sind
*/
if (sigCount == AppSetup.flock_count)
{
sigCount = 0;
this.notify ();
};
}
}
5.2.1.8 FlockSeq.java
/*
* Klasse(n):
Holger Rohde
FlockSeq
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 51 von 98
* Bemerkungen: *
* Datei:
FlockSeq.java
Autor:
Holger Rohde
* Datum:
03.11.05
Version: 0.3
*
* Historie:
*
* 26.12.05 - Umfliegen der Hindernisse hinzugefuegt.
* 17.12.05 - Signalisierung fuer Auftreffen auf die Weltgrenzen
*
hinzugefuegt
*/
package ani;
import javax.vecmath.Color3f;
import javax.vecmath.Vector3f;
import util.AppSetup;
/*
* Klasse erweitert AbstractFlock um die fuer die sequentielle
* Berechnung benoetigen Eigenschaften.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* keine
*
* oeffentliche Methoden:
* ---------------------*
* updateFlock
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class FlockSeq extends AbstractFlock
{
public FlockSeq (Color3f birdColor, World world, int range)
{
super (birdColor, world, range);
}
/*
* Berechnung der Kraefte und Erkennung von Hindernissen fuer jeden
* Vogel des Schwarms
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void updateFlock ()
{
Holger Rohde
WS 2005/2006
Seite 52 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Bird b = null;
for (int i = 0; i < birds.size (); i++)
{
b = birds.getBird (i);
/*
* der Vogel muss umkehren wenn er die Begrenzung der Welt
* erreicht hat
*/
if (!b.getBs ().intersect (world.getBs ()))
{
Vector3f turn = new Vector3f (-b.getPosition ().x,
-b.getPosition ().y, -b.getPosition ().z);
b.addForce (turn);
/*
* Wenn der Vogel die Weltbegrenzung erreicht hat soll dies
* durch eine Veraenderung der Farbe signalisiert werden
*/
if (AppSetup.world_bounds == true)
{
b.setBoundsColoringAttributes (WORLD_HIT_CA);
};
}
/* Wenn der Vogel auf ein Hindernis trifft soll er umdrehen
else if (AppSetup.obstacles && world.intersectObstacle (b))
{
Vector3f turn = new Vector3f (-b.getPosition ().x, 0,
-b.getPosition ().z);
b.addForce (turn);
/* Signalisieren der Hindernisserkennung
b.setBoundsColoringAttributes (OBS_HIT_CA);
*/
}
else
{
/* Kraefte berechnen und zwischenspeichern
b.addForce (seperation (b));
b.addForce (cohesion (b));
b.addForce (alignment (b));
/* Farbe zuruecksetzen wenn der Vogel im normalen Raum ist
b.setBoundsColoringAttributes (null);
};
};
/* Vogeldaten anhand der berechneten Kräfte aktualisieren
for (int i = 0; i < birds.size (); i++)
{
b = birds.getBird (i);
b.update (parameter);
};
*/
*/
*/
*/
}
}
5.2.1.9 FlockThr.java
/*
*
*
*
*
*
Klasse(n):
FlockThr
Bemerkungen: Datei:
Datum:
Holger Rohde
FlockThr.java
23.12.05
Autor:
Holger Rohde
Version: 0.2
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 53 von 98
*
* Historie:
*
* 26.12.05 - Umfliegen der Hindernisse hinzugefuegt.
*/
package ani;
import javax.vecmath.Color3f;
import javax.vecmath.Vector3f;
import util.AppSetup;
/*
* Klasse erweitert AbstractFlock um die fuer die parallele Berechnung
* benoetigen Eigenschaften.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* manager - Referenz auf das FlockManagerThr-Objekt fuer den Aufruf
*
der Methode signal()
*
* oeffentliche Methoden:
* ---------------------*
* run
* signal
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class FlockThr extends AbstractFlock implements Runnable
{
private FlockManagerThr manager = null;
public FlockThr (Color3f birdColor, World world,
FlockManagerThr manager, int range)
{
super (birdColor, world, range);
this.manager = manager;
}
/*
* Berechnung der Kraefte und Erkennung von Hindernissen fuer jeden
* Vogel des Schwarms
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
InterruptedException
*/
public synchronized void run ()
{
Holger Rohde
WS 2005/2006
Seite 54 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
while (true)
{
Bird b = null;
/* Thread nicht beenden
*/
for (int i = 0; i < birds.size (); i++)
{
b = birds.getBird (i);
/*
* der Vogel muss umkehren wenn er die Begrenzung der Welt
* erreicht hat
*/
if (!b.getBs ().intersect (world.getBs ()))
{
Vector3f turn = new Vector3f (-b.getPosition ().x,
-b.getPosition ().y, -b.getPosition ().z);
b.addForce (turn);
/*
* Wenn der Vogel die Weltbegrenzung erreicht hat soll dies
* durch eine Veraenderung der Farbe signalisiert werden
*/
if (AppSetup.world_bounds == true)
{
b.setBoundsColoringAttributes (WORLD_HIT_CA);
};
}
/* Wenn der Vogel auf ein Hindernis trifft soll er umdrehen
*/
else if (AppSetup.obstacles && world.intersectObstacle (b))
{
/* Funktioniert so nicht immer / Fallunterscheidung noetig */
Vector3f turn = new Vector3f (-b.getPosition ().x, 0,
-b.getPosition ().z);
b.addForce (turn);
/* Signalisieren der Hindernisserkennung
b.setBoundsColoringAttributes (OBS_HIT_CA);
*/
}
else
{
/* Kraefte berechnen und zwischenspeichern
b.addForce (seperation (b));
b.addForce (cohesion (b));
b.addForce (alignment (b));
/* Farbe zuruecksetzen wenn der Vogel im normalen Raum ist
b.setBoundsColoringAttributes (null);
};
*/
*/
};
/* Vogeldaten anhand der berechneten Kräfte aktualisieren
*/
for (int i = 0; i < birds.size (); i++)
{
b = birds.getBird (i);
b.update (parameter);
};
manager.signal ();
/* Ende der Berechnung melden */
/* Warten bis zum naechsten Durchlauf
*/
try
{
this.wait();
}
catch (InterruptedException e)
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 55 von 98
{
e.printStackTrace();
};
}
}
/*
* Kapselt den Aufruf der Methode notify(). Ermoeglicht deren Aufruf
* durch einen anderen Thread.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public synchronized void signal ()
{
this.notify ();
}
}
5.2.1.10 GlobalLight.java
/*
* Klasse(n):
GlobalLight
* Bemerkungen: *
* Datei:
GlobalLight.java
Autor:
Holger Rohde
* Datum:
18.11.05
Version: 0.2
*
* Historie:
*
* 20.11.05 - Einflussbereich des Lichts erweitert
*
*/
package ani;
import
import
import
import
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
javax.media.j3d.AmbientLight;
javax.media.j3d.BoundingBox;
javax.media.j3d.BranchGroup;
javax.media.j3d.DirectionalLight;
Licht fuer jedes Objekt der Szene das ein Material besitzt.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------keine
oeffentliche Methoden:
---------------------keine
private Methoden:
----------------------
Holger Rohde
WS 2005/2006
Seite 56 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
*
* keine
*
*/
public class GlobalLight extends BranchGroup
{
public GlobalLight ()
{
DirectionalLight directional = new DirectionalLight ();
AmbientLight ambient = new AmbientLight ();
BoundingBox bounds = new BoundingBox ();
/* Licht wirkt auf jedes Objekt in diesem Bereich
bounds.setLower (-10.0 ,-10.0, -10.0);
bounds.setUpper (10.0 , 10.0, 10.0);
*/
directional.setInfluencingBounds (bounds);
ambient.setInfluencingBounds (bounds);
this.addChild (directional);
this.addChild (ambient);
}
}
5.2.1.11 Obstacle.java
/*
* Klasse(n):
Obstacle
* Bemerkungen: *
* Datei:
Obstacle.java
* Datum:
26.12.05
*
* Historie:
*
* keine Aenderungen
*
*/
package ani;
import
import
import
import
import
import
import
import
import
import
/*
*
*
*
*
*
*
*
*
*
*
Autor:
Holger Rohde
Version: 0.1
javax.media.j3d.Appearance;
javax.media.j3d.BoundingBox;
javax.media.j3d.BranchGroup;
javax.media.j3d.PolygonAttributes;
javax.media.j3d.Transform3D;
javax.media.j3d.TransformGroup;
javax.media.j3d.TransparencyAttributes;
javax.vecmath.Point3d;
javax.vecmath.Vector3f;
com.sun.j3d.utils.geometry.Cylinder;
Gruppe realisiert ein einfaches aus einem Zylinder bestehendes
Hindernis und dessen Grenzen für die Kollisionserkennung.
oeffentliche Daten:
---------------------keine
private Daten:
----------------------
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 57 von 98
*
* bounds - Die imaginaeren Grenzen des Hindernis
*
* oeffentliche Methoden:
* ---------------------*
* Getter / Setter:
*
* getBs
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class Obstacle extends BranchGroup
{
private BoundingBox bounds = new BoundingBox ();
public Obstacle (Vector3f position, float size)
{
Appearance obstacleAp = new Appearance ();
TransparencyAttributes obstacleTa = new TransparencyAttributes ();
PolygonAttributes obstaclePa = new PolygonAttributes ();
TransformGroup ostacleTg = new TransformGroup ();
Transform3D translation = new Transform3D ();
Cylinder obstacleCylinder = new Cylinder (size, 2F);
/* Hindernis auf uebergebene Position schieben
translation.setTranslation (position);
ostacleTg.setTransform (translation);
*/
/*
* die Grenzen sollen groesser als das Objekt an sich sein damit
* die Voegel etwas Spielraum zum Ausweichen haben
*/
size = size * 2.1F;
bounds.setUpper (new Point3d (position.x + size, 1,
position.z + size));
bounds.setLower (new Point3d (position.x - size, -1,
position.z - size));
obstaclePa.setPolygonMode (PolygonAttributes.POLYGON_LINE);
obstacleTa.setTransparencyMode (TransparencyAttributes.NICEST);
obstacleTa.setTransparency (0.8F);
obstacleAp.setPolygonAttributes (obstaclePa);
obstacleAp.setTransparencyAttributes(obstacleTa);
obstacleCylinder.setAppearance (obstacleAp);
ostacleTg.addChild(obstacleCylinder);
this.addChild(ostacleTg);
}
/*
* Gibt die Grenzen des Hindernis zurueck.
*
* Eingabeparameter: -
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 58 von 98
* Ausgabeparameter: BoundingBox bounds
* Fehlerausgaenge:
*/
public BoundingBox getBs ()
{
return bounds;
}
}
5.2.1.12 World.java
/*
* Klasse(n):
World
* Bemerkungen: *
* Datei:
World.java
Autor:
Holger Rohde
* Datum:
01.11.05
Version: 0.4
*
* Historie:
*
* 26.12.05 - Hindernisse mit Gruppe hinzugefuegt / Methoden "public
*
void switchObstacles ()" und "public boolean
*
intersectObstacle (Bird b)" hinzugefuegt.
* 23.12.05 - Farbe der Bodenplatte veraendert.
* 20.12.05 - Methode "public void switchBounds ()" und extra Gruppe
*
fuer den Quader der Begrenzung hinzugefuegt.
*
*/
package ani;
import
import
import
import
import
import
import
import
import
import
import
import
com.sun.j3d.utils.geometry.Box;
javax.media.j3d.Appearance;
javax.media.j3d.BoundingBox;
javax.media.j3d.BranchGroup;
javax.media.j3d.ColoringAttributes;
javax.media.j3d.PolygonAttributes;
javax.media.j3d.Transform3D;
javax.media.j3d.TransformGroup;
javax.media.j3d.TransparencyAttributes;
javax.vecmath.Color3f;
javax.vecmath.Point3d;
javax.vecmath.Vector3f;
import util.AppSetup;
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Die Umgebung der Voegel. Besteht aus den Hindernissen, den Grenzen
und einer Bodenplatte.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------obstacle1
obstacle2
obstacle3
obstacleGroup
boundsGroup
Holger Rohde
-
Hindernis hinten links
Hindernis vorne links
Hindernis hinten mitte
BranchGroup fuer die Hindernisse
BranchGroup fuer die Anzeige Weltbegrenzung
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 59 von 98
* bounds
- Die imaginaeren Grenzen der Welt
*
* oeffentliche Methoden:
* ---------------------*
* intersectObstacle
* switchBounds
* switchObstacles
*
* Getter / Setter:
*
* getBs
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class World extends BranchGroup
{
private Obstacle obstacle1 = new Obstacle (
new Vector3f (-1.5F, 0.0F, -1.3F), 0.2F);
private Obstacle obstacle2 = new Obstacle (
new Vector3f (-1.2F, 0.0F, 1.2F), 0.3F);
private Obstacle obstacle3 = new Obstacle (
new Vector3f (0.0F, 0.0F, -1.7F), 0.2F);
private BoundingBox bounds = new BoundingBox ();
/*
* Nur Gruppen koennen bei laufender Animation hinzugefuegt und
* entfernt werden. Deshalb benoetigten wir eine extra Gruppe fuer
* die Hindernisse und den Quader der Weltbegrenzung. Die Hindernisse
* sind zwar jeweils selbst eine Gruppe sollen aber immer alle
* entfernt oder hinzugefuegt werden. Deshalb werden sie nochmal in
* einer Gruppe zusammengefasst.
*/
private BranchGroup obstacleGroup = new BranchGroup ();
private BranchGroup boundsGroup = new BranchGroup ();
public World ()
{
Appearance groundAp = new Appearance ();
Appearance boundsAp = new Appearance ();
PolygonAttributes boundsPa = new PolygonAttributes ();
TransformGroup tg = new TransformGroup ();
Transform3D move = new Transform3D ();
Color3f groundColor = new Color3f (0.25F, 0.25F, 0.25F);
Box boundsBox = new Box (2.0F, 1.0F, 2.0F, boundsAp);
Box groundBox = new Box (2.0F, 0.05F, 2.0F, groundAp);
this.setCapability (BranchGroup.ALLOW_CHILDREN_WRITE);
this.setCapability (BranchGroup.ALLOW_CHILDREN_EXTEND);
tg.setCapability (TransformGroup.ALLOW_TRANSFORM_READ);
tg.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
obstacleGroup.setCapability (BranchGroup.ALLOW_DETACH);
boundsGroup.setCapability (BranchGroup.ALLOW_DETACH);
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 60 von 98
groundAp.setColoringAttributes (new ColoringAttributes (groundColor,
ColoringAttributes.NICEST));
boundsAp.setTransparencyAttributes (new TransparencyAttributes (
TransparencyAttributes.NICEST, 0.8F));
/* Groesse der Welt festlegen
bounds.setLower (new Point3d (-2, -1, -2));
bounds.setUpper (new Point3d (2, 1, 2));
*/
/* nur Linien der Begrenzung anzeigen
boundsPa.setPolygonMode (PolygonAttributes.POLYGON_LINE);
boundsPa.setCullFace (PolygonAttributes.CULL_NONE);
boundsAp.setPolygonAttributes (boundsPa);
boundsBox.setAppearance (boundsAp);
*/
/* Bodenplatte nach unten verschieben und hinzufuegen
move.setTranslation (new Vector3f (0.0F, -1.4F, 0.0F));
tg.setTransform(move);
tg.addChild(groundBox);
this.addChild (tg);
*/
boundsGroup.addChild (boundsBox);
obstacleGroup.addChild (obstacle1);
obstacleGroup.addChild (obstacle2);
obstacleGroup.addChild (obstacle3);
if (AppSetup.obstacles == true)
{
this.addChild (obstacleGroup);
};
if (AppSetup.world_bounds == true)
{
this.addChild (boundsGroup);
};
}
/*
* Ermitteln ob der Kollisionsbereich des Vogels eine Ueberschneidung
* mit den Kollisionsbereichen der Hindernisse besitzt.
*
* Eingabeparameter: Bird b
* Ausgabeparameter: boolean ret
* Fehlerausgaenge:
*/
public boolean intersectObstacle (Bird b)
{
boolean ret;
ret = b.getBs().intersect(obstacle1.getBs()) ||
b.getBs().intersect(obstacle2.getBs()) ||
b.getBs().intersect(obstacle3.getBs());
return ret;
}
/*
* Visualisierung der Weltbegrenzungen ein- und ausschalten.
*
* Eingabeparameter: * Ausgabeparameter: -
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
* Fehlerausgaenge:
*/
public void switchBounds ()
{
/* Grenzen werden gerade angezeigt
if (boundsGroup.isLive () == true)
{
AppSetup.world_bounds = false;
this.removeChild (boundsGroup);
}
else
{
AppSetup.world_bounds = true;
this.addChild (boundsGroup);
};
}
/*
* Visualisierung der Hindernisse ein- und ausschalten.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void switchObstacles ()
{
/* Hindernisse werden gerade angezeigt
if (obstacleGroup.isLive () == true)
{
AppSetup.obstacles = false;
this.removeChild (obstacleGroup);
}
else
{
AppSetup.obstacles = true;
this.addChild (obstacleGroup);
};
}
Seite 61 von 98
*/
*/
/*
* Rueckgabe der Grenzen der Welt zur Ueberpruefung ob ein Vogel diese
* ueberschritten hat.
*
* Eingabeparameter: * Ausgabeparameter: BoundingBox bounds
* Fehlerausgaenge:
*/
public BoundingBox getBs ()
{
return bounds;
}
}
5.2.2 Packet gui
5.2.2.1 ControlPanel.java
/*
* Klasse(n):
ControlPanel
* Bemerkungen: Enthaelt die inneren Klassen AngleControl,
Holger Rohde
WS 2005/2006
Seite 62 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
*
*
* Datei:
* Datum:
*
* Historie:
*
* 21.12.05 * 10.12.05 *
* 08.12.05 *
*/
package gui;
DistanceControl, MiscControl und StrengthControl.
ControlPanel.java
07.12.05
Rand um das Panel gelegt.
Ausgabe der aktuellen Einstellungen bei Aufruf von
"public void updateAnimation ()" und aktivem Debugging.
15 Pixel Abstand zwischen den einzelnen Kontrollbereichen
gesetzt.
import
import
import
import
import
import
import
import
java.awt.GridLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.AdjustmentEvent;
java.awt.event.AdjustmentListener;
javax.swing.JButton;
javax.swing.JPanel;
javax.swing.border.BevelBorder;
import
import
import
import
import
i18n.Messages;
util.AppSetup;
util.ExtScrollBar;
util.ParameterSet;
ani.AniPanel;
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Autor:
Holger Rohde
Version: 0.4
Das oberste Panel der unteren Kontrollelemente. Die Kontrollen werden
ueber veschiedene innere Klassen zusammengebaut.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------FAC
- Standardfaktor fuer die Umrechnung der Ganzzahlen
der Schieberegler in Gleitkommazahlen
FAC_FORCE
- Faktor fuer die Umrechnung des Schiebereglers
maxForce
FAC_ANGLE
- Faktor fuer die Umrechnung der Schieberegler fuer
Winkel
serialVersionUID - Da JPanel das Interace Serializable
implementiert ist diese Variable notwendig (hat
hier aber keine weitere Funktion)
messages
- Referenz auf die Internationalisierungsklasse
aniPanel
- Referenz auf die Animation
parameter
- Die aktuell eingestellten Werte der Kontrollen
defParameter
- Standardwerte zum Zuruecksetzen der Kontrollen
oeffentliche Methoden:
----------------------
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 63 von 98
* updateAnimation
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class ControlPanel extends JPanel
{
private static int FAC = 100;
private static int FAC_FORCE = 1000;
private static int FAC_ANGLE = 1;
private
private
private
private
private
static final long serialVersionUID = 1;
Messages messages = null;
AniPanel aniPanel = null;
ParameterSet parameter = new ParameterSet ();
ParameterSet defParameter = new ParameterSet ();
public ControlPanel (Messages messages, AniPanel aniPanel)
{
this.messages = messages;
this.aniPanel = aniPanel;
GridLayout grid = new GridLayout (1, 4);
grid.setHgap (15);
this.setLayout (grid);
this.setBorder (new BevelBorder (BevelBorder.LOWERED));
this.add (new AngleControl ());
this.add (new DistanceControl ());
this.add (new StrengthControl ());
this.add (new MiscControl ());
}
/*
* Ubergeben geaenderter Werte an die Animation.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge: */
public void updateAnimation ()
{
aniPanel.updateFlockManager (parameter);
if (AppSetup.debug == true)
{
System.out.println (parameter);
};
}
/*
*
*
*
*
*
*
*
Kontrollelemente fuer die Winkelparamter des Algorithmus.
oeffentliche Daten:
---------------------keine
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 64 von 98
* private Daten:
* ---------------------*
* serialVersionUID - Da JPanel das Interace Serializable
*
implementiert ist diese Variable notwendig (hat
*
hier aber keine weitere Funktion)
* reset
- Button zum Zuruecksetzen der Werte
* alignAngle
- Schieberegler fuer die Kraft "alignment"
* cohAngle
- Schieberegler fuer die Kraft "cohesion"
* sepAngle
- Schieberegler fuer die Kraft "seperation"
* actListener
- Listener fuer die Zuruecksetzen-Funktion
* adjListener
- Listener fuer die Schieberegler
*
* oeffentliche Methoden:
* ---------------------*
* keine
*
* private Methoden:
* ---------------------*
* keine
*
*/
private class AngleControl extends JPanel
{
private static final long serialVersionUID = 1;
private JButton reset = null;
private ExtScrollBar alignAngle = null;
private ExtScrollBar cohAngle = null;
private ExtScrollBar sepAngle = null;
private AngleControl ()
{
GridLayout grid = new GridLayout (4, 1);
reset = new JButton (messages.getString ("reset_angle"));
/* Schieberegler fuer die Winkel jeweils mit Min 1 und Max 180 */
alignAngle = new ExtScrollBar (messages.getString (
"alignment_angle"), (int) parameter.getAlignAngle (), 1, 180);
cohAngle = new ExtScrollBar (messages.getString (
"cohesion_angle"), (int) parameter.getCohAngle (), 1, 180);
sepAngle = new ExtScrollBar (messages.getString (
"seperation_angle"), (int) parameter.getSepAngle (), 1, 180);
reset.addActionListener (actListener);
alignAngle.addAdjustmentListener (adjListener);
cohAngle.addAdjustmentListener (adjListener);
sepAngle.addAdjustmentListener (adjListener);
this.setLayout (grid);
this.add (cohAngle);
this.add (sepAngle);
this.add (alignAngle);
this.add (reset);
}
private ActionListener actListener = new ActionListener ()
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 65 von 98
{
public void actionPerformed (ActionEvent e)
{
alignAngle.setFloatValue (FAC_ANGLE,
defParameter.getAlignAngle ());
cohAngle.setFloatValue (FAC_ANGLE,
defParameter.getCohAngle ());
sepAngle.setFloatValue (FAC_ANGLE,
defParameter.getSepAngle ());
updateAnimation ();
}
};
private AdjustmentListener adjListener = new AdjustmentListener ()
{
public void adjustmentValueChanged (AdjustmentEvent e)
{
alignAngle.updateToolTip ();
cohAngle.updateToolTip ();
sepAngle.updateToolTip ();
parameter.setAlignAngle (
alignAngle.getFloatValue (FAC_ANGLE));
parameter.setCohAngle (cohAngle.getFloatValue (FAC_ANGLE));
parameter.setSepAngle (sepAngle.getFloatValue (FAC_ANGLE));
updateAnimation ();
}
};
}
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Kontrollelemente fuer die Distanzparamter des Algorithmus.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------serialVersionUID - Da JPanel das Interace Serializable
implementiert ist diese Variable notwendig (hat
hier aber keine weitere Funktion)
reset
- Button zum Zuruecksetzen der Werte
alignDistance
- Schieberegler fuer die Kraft "alignment"
cohDistance
- Schieberegler fuer die Kraft "cohesion"
sepDistance
- Schieberegler fuer die Kraft "seperation"
actListener
- Listener fuer die Zuruecksetzen-Funktion
adjListener
- Listener fuer die Schieberegler
oeffentliche Methoden:
---------------------keine
private Methoden:
---------------------keine
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 66 von 98
*/
private class DistanceControl extends JPanel
{
private static final long serialVersionUID = 1;
private JButton reset = null;
private ExtScrollBar alignDistance = null;
private ExtScrollBar cohDistance = null;
private ExtScrollBar sepDistance = null;
private DistanceControl ()
{
GridLayout grid = new GridLayout (4, 1);
reset = new JButton (messages.getString ("reset_distance"));
/* Schieberegler fuer die Distanz jeweils mit Min 1 und Max 200 */
alignDistance = new ExtScrollBar (messages.getString (
"alignment_distance"), (int) (parameter.getAlignDistance () *
FAC), 1, 200);
cohDistance = new ExtScrollBar (messages.getString (
"cohesion_distance"), (int) (parameter.getCohDistance () *
FAC), 1, 200);
sepDistance = new ExtScrollBar (messages.getString (
"seperation_distance"), (int) (parameter.getSepDistance () *
FAC), 1, 200);
reset.addActionListener (actListener);
alignDistance.addAdjustmentListener (adjListener);
cohDistance.addAdjustmentListener (adjListener);
sepDistance.addAdjustmentListener (adjListener);
this.setLayout (grid);
this.add (cohDistance);
this.add (sepDistance);
this.add (alignDistance);
this.add (reset);
}
private ActionListener actListener = new ActionListener ()
{
public void actionPerformed (ActionEvent e)
{
alignDistance.setFloatValue (FAC,
defParameter.getAlignDistance ());
cohDistance.setFloatValue (FAC,
defParameter.getCohDistance ());
sepDistance.setFloatValue (FAC,
defParameter.getSepDistance ());
updateAnimation ();
}
};
private AdjustmentListener adjListener = new AdjustmentListener ()
{
public void adjustmentValueChanged (AdjustmentEvent e)
{
alignDistance.updateToolTip ();
cohDistance.updateToolTip ();
sepDistance.updateToolTip ();
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 67 von 98
parameter.setAlignDistance (
alignDistance.getFloatValue (FAC));
parameter.setCohDistance (cohDistance.getFloatValue (FAC));
parameter.setSepDistance (sepDistance.getFloatValue (FAC));
updateAnimation ();
}
};
}
/*
* Kontrollelemente fuer allgemeine Parameter der Simualtion.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* serialVersionUID - Da JPanel das Interace Serializable
*
implementiert ist diese Variable notwendig (hat
*
hier aber keine weitere Funktion)
* reset
- Button zum Zuruecksetzen der Werte
* maxForce
- Schieberegler fuer die maximale Kraft die auf
*
Voegel einwirken darf
* maxSpeed
- Schieberegler fuer die maximale Geschwindigkeit
*
der Voegel
* birdCount
- Schieberegler fuer die Anzahl der Voegel pro
*
Schwarm
* actListener
- Listener fuer die Zuruecksetzen-Funktion
* adjListener
- Listener fuer die Schieberegler
*
* oeffentliche Methoden:
* ---------------------*
* keine
*
* private Methoden:
* ---------------------*
* keine
*
*/
private class MiscControl extends JPanel
{
private JButton reset = null;
private ExtScrollBar maxForce = null;
private ExtScrollBar maxSpeed = null;
private ExtScrollBar birdCount = null;
private static final long serialVersionUID = 1;
private MiscControl ()
{
GridLayout grid = new GridLayout (4, 1);
reset = new JButton (messages.getString ("reset_misc"));
/* Schieberegler fuer die Distanz jeweils mit Min 1 und Max 50
maxForce = new ExtScrollBar (messages.getString ("max_force"),
Holger Rohde
*/
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 68 von 98
(int) (parameter.getMaxForce () * FAC_FORCE), 1, 50);
maxSpeed = new ExtScrollBar (messages.getString ("max_speed"),
(int) (parameter.getMaxSpeed () * FAC), 1, 20);
birdCount = new ExtScrollBar (messages.getString ("bird_count"),
parameter.getBirdCount (), 1, AppSetup.bird_count_max);
reset.addActionListener (actListener);
maxForce.addAdjustmentListener (adjListener);
maxSpeed.addAdjustmentListener (adjListener);
birdCount.addAdjustmentListener (adjListener);
this.setLayout (grid);
this.add (maxForce);
this.add (maxSpeed);
this.add (birdCount);
this.add (reset);
}
private ActionListener actListener = new ActionListener ()
{
public void actionPerformed (ActionEvent e)
{
maxForce.setFloatValue (FAC_FORCE,
defParameter.getMaxForce ());
maxSpeed.setFloatValue (FAC, defParameter.getMaxSpeed ());
birdCount.setFloatValue (1, defParameter.getBirdCount ());
updateAnimation ();
}
};
private AdjustmentListener adjListener = new AdjustmentListener ()
{
public void adjustmentValueChanged (AdjustmentEvent e)
{
maxForce.updateToolTip ();
maxSpeed.updateToolTip ();
birdCount.updateToolTip ();
parameter.setMaxForce (maxForce.getFloatValue (FAC_FORCE));
parameter.setMaxSpeed (maxSpeed.getFloatValue (FAC));
parameter.setBirdCount (birdCount.getValue ());
updateAnimation ();
}
};
}
/*
*
*
*
*
*
*
*
*
*
*
*
*
Kontrollelemente fuer die Gewichtung der Paramter des Algorithmus.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------serialVersionUID - Da JPanel das Interace Serializable
implementiert ist diese Variable notwendig (hat
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 69 von 98
*
hier aber keine weitere Funktion)
* reset
- Button zum Zuruecksetzen der Werte
* alignStrength
- Schieberegler fuer die Kraft "alignment"
* cohStrength
- Schieberegler fuer die Kraft "cohesion"
* sepStrength
- Schieberegler fuer die Kraft "seperation"
* actListener
- Listener fuer die Zuruecksetzen-Funktion
* adjListener
- Listener fuer die Schieberegler
*
* oeffentliche Methoden:
* ---------------------*
* keine
*
* private Methoden:
* ---------------------*
* keine
*
*/
private class StrengthControl extends JPanel
{
private static final long serialVersionUID = 1;
private JButton reset = null;
private ExtScrollBar alignStrength = null;
private ExtScrollBar cohStrength = null;
private ExtScrollBar sepStrength = null;
private StrengthControl ()
{
GridLayout grid = new GridLayout (4, 1);
reset = new JButton (messages.getString ("reset_strength"));
/* Schieberegler fuer die Distanz jeweils mit Min 1 und Max 100 */
alignStrength = new ExtScrollBar (messages.getString (
"alignment"), (int) (parameter.getAliStrength () * FAC));
cohStrength = new ExtScrollBar (messages.getString ("cohesion"),
(int) (parameter.getCohStrength () * FAC));
sepStrength = new ExtScrollBar (messages.getString (
"seperation"), (int) (parameter.getSepStrength () * FAC));
reset.addActionListener (actListener);
alignStrength.addAdjustmentListener (adjListener);
cohStrength.addAdjustmentListener (adjListener);
sepStrength.addAdjustmentListener (adjListener);
this.setLayout (grid);
this.add (cohStrength);
this.add (sepStrength);
this.add (alignStrength);
this.add (reset);
}
private ActionListener actListener = new ActionListener ()
{
public void actionPerformed (ActionEvent e)
{
alignStrength.setFloatValue (FAC,
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 70 von 98
defParameter.getAliStrength ());
cohStrength.setFloatValue (FAC,
defParameter.getCohStrength ());
sepStrength.setFloatValue (FAC,
defParameter.getSepStrength ());
updateAnimation ();
}
};
private AdjustmentListener adjListener = new AdjustmentListener ()
{
public void adjustmentValueChanged (AdjustmentEvent e)
{
alignStrength.updateToolTip ();
cohStrength.updateToolTip ();
sepStrength.updateToolTip ();
parameter.setAliStrength (alignStrength.getFloatValue (FAC));
parameter.setCohStrength (cohStrength.getFloatValue (FAC));
parameter.setSepStrength (sepStrength.getFloatValue (FAC));
updateAnimation ();
}
};
}
}
5.2.2.2 InfoPanel.java
/*
* Klasse(n):
InfoPanel
* Bemerkungen: *
* Datei:
InfoPanel.java
Autor:
Holger Rohde
* Datum:
17.12.05
Version: 0.2
*
* Historie:
*
* 26.12.05 - Aktualisierungsrate einstellbar ueber Konstante.
*/
package gui;
import java.awt.GridLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import i18n.Messages;
import util.Timer;
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
Erweiterung der Klasse JPanel zur Anzeige der Simulationsmesswerte.
Die Werte werden ueber Labels ausgegeben.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------UPD_ITR
- Aktualisierungsrate des Panels
serialVersionUID - Da JPanel das Interace Serializable
implementiert ist diese Variable notwendig (hat
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 71 von 98
*
hier aber keine weitere Funktion)
* messages
- Referenz auf die Internationalisierungsklasse
* timeValue
- JLabel zur Anzeige der Rechenzeit
* avgValue
- JLabel zur Anzeige der Durchschnittszeit
* hitsValue
- JLabel zur Anzeige der durlaufenen Iterationen
* totalValue
- JLabel zur Anzeige der Gesamtzeit
* updateIter
- Hilfsvariable fuer die Aktualisierungsrate
*
* oeffentliche Methoden:
* ---------------------*
* getString
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class InfoPanel extends JPanel
{
private static int UPD_ITR = 5;
private
private
private
private
private
private
private
static final long serialVersionUID = 1;
Messages messages = null;
JLabel timeValue = new JLabel ("0");
JLabel avgValue = new JLabel ("0");
JLabel hitsValue = new JLabel ("0");
JLabel totalValue = new JLabel ("0");
int updateIter = 0;
public InfoPanel (Messages messages)
{
this.messages = messages;
JLabel timeLabel = new JLabel (messages.getString ("info_time") +
":");
JLabel avgLabel = new JLabel (messages.getString ("info_avg") +
":");
JLabel hitsLabel = new JLabel (messages.getString ("info_frames") +
":");
JLabel totalLabel = new JLabel (messages.getString ("info_total") +
":");
this.setLayout (new GridLayout ());
this.add (new JLabel ());
this.add (timeLabel);
this.add (timeValue);
this.add (avgLabel);
this.add (avgValue);
this.add (totalLabel);
this.add (totalValue);
this.add (hitsLabel);
this.add (hitsValue);
}
/*
* Aktualisierung der Werte des Panel.
*
* Eingabeparameter: Timer timer
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
* Ausgabeparameter: * Fehlerausgaenge:
*/
public void updateTime (Timer timer)
{
updateIter++;
/* Aktualisierung nur nach jeweils UPD_ITR Aufrufen
if (updateIter == UPD_ITR)
{
updateIter = 0;
timeValue.setText (timer.getTime ());
avgValue.setText (timer.getAvg ());
hitsValue.setText (timer.getHits ());
totalValue.setText (timer.getTotal ());
};
}
Seite 72 von 98
*/
}
5.2.2.3 MainFrame.java
/*
* Klasse(n):
MainFrame
* Bemerkungen: Enthaelt die innere Klasse FrameMenu.
*
* Datei:
MainFrame.java
Autor:
Holger Rohde
* Datum:
01.11.05
Version: 1.1
*
* Historie:
*
* 28.12.05 - JMenuItem im Einstellungsmenue in JCheckBoxMenuItem
*
geaendert.
* 27.12.05 - Das Ueberlagern des Menu durch die Animation behoben
*
(http://forum.java.sun.com/thread.jspa?threadID=595810&
*
messageID=3887806).
* 26.12.05 - Menuepunkt "Hindernisse" hinzugefuegt. / Parameter -t zur
*
Aktivierung des Testmodus hinzugefuegt.
* 25.12.05 - Menuepunkt "Vogel Begrenzung" hinzugefuegt.
* 23.12.05 - Parameter -p zur Aktivierung der parallelen Variante in
*
die Auswertung der Argumente hinzugefuegt.
* 22.12.05 - Groessenanpassung des Anwendungsfensters deaktiviert.
* 20.12.05 - Menuepunkt "Welt Begrenzung" hinzugefuegt.
* 19.12.05 - Innere Klasse FrameMenu hinzugefuegt.
* 17.12.05 - InfoPanel hinzugefuegt.
* 07.12.05 - ControlPanel hinzugefuegt.
*/
package gui;
import
import
import
import
import
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.JCheckBoxMenuItem;
javax.swing.JFrame;
javax.swing.JMenu;
javax.swing.JMenuBar;
javax.swing.JMenuItem;
javax.swing.SwingUtilities;
javax.swing.UIManager;
javax.swing.UnsupportedLookAndFeelException;
import i18n.Messages;
import util.AppSetup;
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 73 von 98
import ani.AniPanel;
/*
* Oberstes Fenster der Anwendung und main-Methode.
*
* oeffentliche Daten:
* ---------------------* keine
*
* private Daten:
* ---------------------*
* BENCH_FORCE
- Maximale Kraft die auf die Voegel im Testmodus
*
einwirkt
* BENCH_SPEED
- Geschwindigkeit der Voegel im Testmodus
* BENCH_MAX_BIRDS - Die maximale Vogel-Anzahl im Testmodus
* serialVersionUID - Da JFrame das Interace Serializable
*
implementiert ist diese Variable notwendig (hat
*
hier aber keine weitere Funktion)
* messages
- Klasse mit gekapseltem Zugriff auf die
*
Internationalisierungsdatei
* info
- Das Panel mit den aktuellen Messwerten des
*
Algorithmus
* ani
- Das Panel mit der Java3D Animation
* control
- Das Panel mit den Kontrollelementen zur
*
Steuerung der Simulationsparameter
*
*
* oeffentliche Methoden:
* ---------------------*
* main
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class MainFrame extends JFrame
{
private static float BENCH_FORCE = 0.05F;
private static float BENCH_SPEED = 0.2F;
private static int BENCH_MAX_BIRDS = 1000;
private
private
private
private
private
static final long serialVersionUID = 1;
Messages messages = new Messages ();
InfoPanel info = new InfoPanel (messages);
AniPanel ani = new AniPanel (info);
ControlPanel control = new ControlPanel (messages, ani);
public MainFrame ()
{
this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
this.setTitle (messages.getString ("title"));
this.setLayout (new BorderLayout ());
this.setJMenuBar (new FrameMenu ());
this.setResizable (false);
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 74 von 98
this.add (info, BorderLayout.NORTH);
this.add (ani, BorderLayout.CENTER);
this.add (control, BorderLayout.SOUTH);
this.pack ();
this.setVisible (true);
}
/*
* Startpunkt der Anwendung. Die uebergebenen Argumente werden
* ausgewertet und das Fenster erzeugt.
*
* Eingabeparameter: String[] args
* Ausgabeparameter: * Fehlerausgaenge:
NumberFormatException
*
ClassNotFoundException
*
InstantiationException
*
IllegalAccessException
*
UnsupportedLookAndFeelException
*/
public static void main (String[] args)
{
for (int i = 0; i < args.length; i++)
{
if ("-d".equals (args[i]))
/* Statusmeldungen ausgeben
{
AppSetup.debug = true;
}
/* Anzahl der Voegel
else if ("-b".equals (args[i].substring (0, 2)))
{
try
{
AppSetup.bird_count = Integer
.parseInt (args[i].substring (2));
}
catch (NumberFormatException e)
{
e.printStackTrace ();
};
}
else if ("-t".equals (args[i]))
/* Testmodus
{
AppSetup.benchmark = true;
AppSetup.force_def = BENCH_FORCE;
AppSetup.speed_def = BENCH_SPEED;
AppSetup.bird_count_max = BENCH_MAX_BIRDS;
}
else if ("-p".equals (args[i]))
/* Parallele Variante nutzen
{
AppSetup.use_threads = true;
}
/*Anzahl Vogelschwaerme
else if ("-f".equals (args[i].substring (0, 2)))
{
try
{
AppSetup.flock_count = Integer.parseInt (args[i]
.substring (2));
}
Holger Rohde
*/
*/
*/
*/
*/
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 75 von 98
catch (NumberFormatException e)
{
e.printStackTrace ();
};
};
};
/* Funktioniert nur vor der ersten Erstellung eines Frames
try
{
UIManager.setLookAndFeel (UIManager
.getSystemLookAndFeelClassName ());
}
catch (ClassNotFoundException e)
{
e.printStackTrace ();
}
catch (InstantiationException e)
{
e.printStackTrace ();
}
catch (IllegalAccessException e)
{
e.printStackTrace ();
}
catch (UnsupportedLookAndFeelException e)
{
e.printStackTrace ();
};
/* Ausfuehrung durch den Event-Dispatching Thread
SwingUtilities.invokeLater (new Runnable ()
{
public void run ()
{
MainFrame mf = new MainFrame ();
}
});
*/
*/
}
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Menu fuer die Anwendung.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------serialVersionUID - Da JMenuBar das Interace Serializable
implementiert ist diese Variable notwendig (hat
hier aber keine weitere Funktion)
menu_01
- Menuepunkt "Beenden"
menu_11
- Menuepunkt "Vogel Begrenzung"
menu_12
- Menuepunkt "Welt Begrenzung"
menu_13
- Menuepunkt "Hindernisse"
menuListener
- Listener fuer Ereignisse im Menue
oeffentliche Methoden:
----------------------
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 76 von 98
*
* keine
*
* private Methoden:
* ---------------------*
* keine
*
*/
private class FrameMenu extends JMenuBar
{
private static final long serialVersionUID = 1;
private JMenuItem menu_01 = null;
private JCheckBoxMenuItem menu_11 = null;
private JCheckBoxMenuItem menu_12 = null;
private JCheckBoxMenuItem menu_13 = null;
private FrameMenu ()
{
JMenu menu_0 = new JMenu (messages.getString ("menu_0"));
JMenu menu_1 = new JMenu (messages.getString ("menu_1"));
menu_01
menu_11
menu_12
menu_13
=
=
=
=
new
new
new
new
JMenuItem (messages.getString ("menu_01"));
JCheckBoxMenuItem (messages.getString ("menu_11"));
JCheckBoxMenuItem (messages.getString ("menu_12"));
JCheckBoxMenuItem (messages.getString ("menu_13"));
menu_01.addActionListener (menuListener);
menu_0.add (menu_01);
menu_11.addActionListener (menuListener);
menu_12.addActionListener (menuListener);
menu_13.addActionListener (menuListener);
menu_1.add (menu_11);
menu_1.add (menu_12);
menu_1.add (menu_13);
/* Ueberlagerung der Menues verhindern
menu_0.getPopupMenu ().setLightWeightPopupEnabled (false);
menu_1.getPopupMenu ().setLightWeightPopupEnabled (false);
*/
menu_11.setSelected (AppSetup.bird_bounds);
menu_12.setSelected (AppSetup.world_bounds);
menu_13.setSelected (AppSetup.obstacles);
this.add (menu_0);
this.add (menu_1);
}
private ActionListener menuListener = new ActionListener ()
{
public void actionPerformed (ActionEvent e)
{
/* Ausgabe des aufgerufenen Menuepunkts
if (AppSetup.debug == true)
{
System.out.println (e);
};
/* Menuepunkt Datei->Beenden
if (menu_01.equals (e.getSource ()))
Holger Rohde
*/
*/
WS 2005/2006
Seite 77 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
{
System.exit (0);
}
/* Menuepunnkt Einstellungen->Welt Begrenzungen
else if (menu_11.equals (e.getSource ()))
{
ani.switchWorldBounds ();
}
/* Menuepunnkt Einstellungen->Vogel Begrenzungen
else if (menu_12.equals (e.getSource ()))
{
ani.switchBirdBounds ();
*/
*/
}
/* Menuepunnkt Einstellungen->Hindernisse
else if (menu_13.equals (e.getSource ()))
{
ani.switchObstacles ();
};
*/
}
};
}
}
5.2.3 Packet i18n
5.2.3.1 Messages.java
/*
* Klasse(n):
* Bemerkungen:
*
* Datei:
* Datum:
*
* Historie:
*
* 15. November
*
*/
package i18n;
Messages
AppSetup.java
01.11.05
Autor:
Holger Rohde
Version: 0.2
2005 - Ausnahmebehandlung in "public String getString
(String key)" erweitert.
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import util.AppSetup;
/*
*
*
*
*
*
*
*
*
*
*
*
Klasse bestimmt die zum aktuellen Standort passende
Internationalisierungsdatei und ermoeglicht den Zugriff auf diese.
oeffentliche Daten:
---------------------keine
private Daten:
----------------------
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 78 von 98
* locale
- Der aktuelle Standord aus der Klasse AppSetup
* resMessages - Die zum Standort passende Internationalisierungsdatei
*
* oeffentliche Methoden:
* ---------------------*
* getString
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class Messages
{
private Locale locale = AppSetup.locale;
private ResourceBundle resMessages = ResourceBundle.getBundle (
"i18n/MessagesBundle", locale);
/*
* Rueckgabe des zum Schluessel passenden Text aus dem aktuellen
* ResourceBundle.
*
* Eingabeparameter: String key
* Ausgabeparameter: String string
* Fehlerausgaenge:
MissingResourceException
*
NullPointerException
*
ClassCastException
*/
public String getString (String key)
{
String string = null;
try
{
string = resMessages.getString (key);
}
catch (MissingResourceException e)
{
e.printStackTrace ();
string = "MISSING RESSOURCE";
}
catch (NullPointerException e)
{
e.printStackTrace ();
string = "KEY IS NULL";
}
catch (ClassCastException e)
{
e.printStackTrace ();
string = "KEY MUST BE A STRING";
};
return string;
}
}
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 79 von 98
5.2.3.2 MessagesBundle_en_US.properties
/*
* Klasse(n):
* Bemerkungen: Lokalisierungsdatei Englisch
*
* Datei:
MessagesBundle_en_US.properties
Autor:
Holger Rohde
* Datum:
01.11.05
Version: 0.7
*
* Historie:
*
* 26.12.05 - Text menu_13 fuer das Anwendungsmenue hinzugefuegt.
* 25.12.05 - Text menu_12 fuer das Anwendungsmenue hinzugefuegt.
* 20.12.05 - Text menu_11 fuer das Anwendungsmenue hinzugefuegt.
* 19.12.05 - Texte menu_0, menu_01 und menu_1 fuer das Anwendungsmenue
*
hinzugefuegt.
* 17.12.05 - Texte info_time, info_avg, info_frames und info_total
*
fuer die Anzeige im Infopanel hinzugefuegt.
* 07.12.05 - Texte reset_strength, reset_angle, reset_distance und
*
reset_misc fuer die Kotrollelemente hinzugefuegt.
*/
title = Flocking
seperation = Seperation
cohesion = Cohesion
alignment = Alignment
seperation_distance = Seperation Distance
cohesion_distance = Cohesion Distance
alignment_distance = Alignment Distance
seperation_angle = Seperation Angle
cohesion_angle = Cohesion Angle
alignment_angle = Alignment Angle
max_force = maximum Force
max_speed = maximum Speed
bird_count = Birds
reset_strength = reset
reset_angle = reset
reset_distance = reset
reset_misc = reset
info_time = calculation time(ms)
info_avg = average(ms)
info_frames = iterations
info_total = total time(ms)
menu_0 = File
menu_01 = Exit
menu_1
menu_11
menu_12
menu_13
=
=
=
=
Settings
World Bounds
Bird Bounds
Obstacles
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 80 von 98
5.2.3.3 MessagesBundle.properties
/*
* Klasse(n):
* Bemerkungen: Standard Lokalisierungsdatei
*
* Datei:
MessagesBundle.properties
Autor:
Holger Rohde
* Datum:
01.11.05
Version: 0.7
*
* Historie:
*
* 26.12.05 - Text menu_13 fuer das Anwendungsmenue hinzugefuegt.
* 25.12.05 - Text menu_12 fuer das Anwendungsmenue hinzugefuegt.
* 20.12.05 - Text menu_11 fuer das Anwendungsmenue hinzugefuegt.
* 19.12.05 - Texte menu_0, menu_01 und menu_1 fuer das Anwendungsmenue
*
hinzugefuegt.
* 17.12.05 - Texte info_time, info_avg, info_frames und info_total
*
fuer die Anzeige im Infopanel hinzugefuegt.
* 07.12.05 - Texte reset_strength, reset_angle, reset_distance und
*
reset_misc fuer die Kotrollelemente hinzugefuegt.
*/
title = Schwarmverhalten
seperation = Vermeidung
cohesion = Zusammenhalt
alignment = Ausrichtung
seperation_distance = Vermeidungsdistanz
cohesion_distance = Zusammenshaltdistanz
alignment_distance = Ausrichtungsdistanz
seperation_angle = Vermeidungswinkel
cohesion_angle = Zusammenhaltswinkel
alignment_angle = Ausrichtungswinkel
max_force = maximale Kraft
max_speed = maximale Geschwindigkeit
bird_count = Vögel
reset_strength = zurücksetzen
reset_angle = zurücksetzen
reset_distance = zurücksetzen
reset_misc = zurücksetzen
info_time = Rechenzeit(ms)
info_avg = Durchschnitt(ms)
info_frames = Iterationen
info_total = Gesamtzeit(ms)
menu_0 = Datei
menu_01 = Beenden
menu_1
menu_11
menu_12
menu_13
=
=
=
=
Einstellungen
Welt Begrenzung
Vogel Begrenzung
Hindernisse
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 81 von 98
5.2.4 Packet util
5.2.4.1 AppSetup.java
/*
* Klasse(n):
AppSetup
* Bemerkungen: *
* Datei:
AppSetup.java
Autor:
Holger Rohde
* Datum:
01.11.05
Version: 0.4
*
* Historie:
*
*
* 26.12.05 - Hinzufuegen der Varaiblen bechmark, BENCH_ITERATIONS und
*
obstacles.
* 25.12.05 - Hinzufuegen der Variablen bird_bounds.
* 23.12.05 - Hinzufuegen der Variablen "use_threads".
*/
package util;
import java.awt.Dimension;
import java.util.Locale;
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Globale Variablen zur Anpassung der Simulation und des Programms.
oeffentliche Daten:
---------------------locale
animationSize
use_threads
debug
benchmark
BENCH_ITERATIONS
world_bounds
bird_bounds
obstacles
flock_count
bird_count
bird_count_max
speed_def
force_def
INIT_WAKEUP
BIRD_SIZE
COH_ANGLE_DEF
Holger Rohde
- Aktueller Standort fuer die
Internationalisierung
- Groesse der Animation
- Parallele Implementierung nutzen
- Statusausgaben auf die Konsole schreiben
- Spezieller Modus fuer die Leistungsmessung
- Anzahl Iterationen fuer einen Testlauf
(Anwendung wird nach Durchlaufen der Iterationen
beendet und Ergebnis wird ausgegeben)
- Anzeige der Grenzen der Vogelwelt
- Anzeige des Kollisionsbereichs um den Vogel
- Anzeige und Umfliegen von Hindernissen
- Anzahl der Vogelschwaerme
- Anzahl Voegel pro Schwarm
- Im Kontrollbereich maximal einstellbare
Vogelzahl
- Maximale Geschwindigkeit des Vogels
(0 < speed <= 0.2)
- Maximale Kraft die auf den Vogel wirkt
(0 < force <= 0.05)
- Zeit in Millisekunden nach der die Simulation
startet
- Groesse des Vogelmodells
- Blickwinkel des Vogels fuer Kraft "cohesion"
(0 < angle <= 179)
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 82 von 98
* SEP_ANGLE_DEF
- Blickwinkel des Vogels fuer Kraft "seperation"
*
(0 < angle <= 179)
* ALIGN_ANGLE_DEF
- Blickwinkel des Vogels fuer Kraft "alignment"
*
(0 < angle <= 179)
* COH_DISTANCE_DEF
- Distanz zu den Nachbarvoegeln fuer Kraft
*
"cohesion" (0 < distance <= 2)
* SEP_DISTANCE_DEF
- Distanz zu den Nachbarvoegeln fuer Kraft
*
"seperation" (0 < distance <= 2)
* ALIGN_DISTANCE_DEF - Distanz zu den Nachbarvoegeln fuer Kraft
*
"alignment" (0 < distance <= 2)
* COH_STRENGTH_DEF
- Staerke der Kraft "cohesion"
*
(0 < strength <= 1)
* SEP_STRENGTH_DEF
- Staerke der Kraft "seperation"
*
(0 < strength <= 1)
* ALIGN_STRENGTH_DEF - Staerke der Kraft "alignment"
*
(0 < strength <= 1)
*
* private Daten:
* ---------------------*
* keine
*
* oeffentliche Methoden:
* ---------------------*
* keine
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class AppSetup
{
// public static Locale locale = new Locale ("en", "US");
public static Locale locale = Locale.getDefault ();
public static Dimension animationSize = new Dimension (1024, 768);
public static boolean use_threads = true;
public static boolean debug = false;
public static boolean benchmark = false;
public static int BENCH_ITERATIONS = 250;
public static boolean world_bounds = true;
public static boolean bird_bounds = true;
public static boolean obstacles = true;
public
public
public
public
public
static
static
static
static
static
int flock_count = 3;
int bird_count = 20;
int bird_count_max = 100;
float speed_def = 0.03F;
float force_def = 0.003F;
public static long INIT_WAKEUP = 1;
public static float BIRD_SIZE = 0.02F;
public static float COH_ANGLE_DEF = 30;
public static float SEP_ANGLE_DEF = 45;
public static float ALIGN_ANGLE_DEF = 80;
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 83 von 98
public static float COH_DISTANCE_DEF = 1.0F;
public static float SEP_DISTANCE_DEF = 1.0F;
public static float ALIGN_DISTANCE_DEF = 1.5F;
public static float COH_STRENGTH_DEF = 0.9F;
public static float SEP_STRENGTH_DEF = 1.0F;
public static float ALIGN_STRENGTH_DEF = 0.6F;
}
5.2.4.2 BirdList.java
/*
* Klasse(n):
BirdList
* Bemerkungen: *
* Datei:
BirdList.java
Autor:
Holger Rohde
* Datum:
03.11.05
Version: 0.2
*
* Historie:
*
* 17.11.05 - Fehlerbehandlung in den Methoden ergaenzt.
*/
package util;
import java.util.ArrayList;
import ani.Bird;
/*
* Erweiterung der Klasse ArrayList zur Ablage von Objekten vom Typ
* Bird.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* serialVersionUID - Da ArrayList das Interace Serializable
*
implementiert ist diese Variable notwendig (hat
*
hier aber keine weitere Funktion)
*
* oeffentliche Methoden:
* ---------------------*
* getBird
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class BirdList extends ArrayList
{
/* ArrayList implementiert Serializable
*/
Holger Rohde
WS 2005/2006
Seite 84 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
private static final long serialVersionUID = 1;
/*
* Rueckgabe des Elements an der Stelle i und Typumwandlung zu
* Bird.
*
* Eingabeparameter: int index
* Ausgabeparameter: Bird ret
* Fehlerausgaenge:
ArrayIndexOutOfBoundsException
*/
public Bird getBird (int index)
{
Bird ret = null;
try
{
ret = (Bird) get (index);
}
catch (ArrayIndexOutOfBoundsException e)
{
e.printStackTrace ();
};
return ret;
}
}
5.2.4.3 ExtScrollBar,java
/*
* Klasse(n):
ExtScrollBar
* Bemerkungen: *
* Datei:
ExtScrollBar.java
* Datum:
06.12.05
*
* Historie:
*
* 08.12.05 - Auf die Werte fuer das Maximum
*
uebergebenen Werte eingestellt
* 07.12.05 - Verschiedene Konstruktoren zur
*
Standardwerten hinzugefuegt.
*/
package util;
import
import
import
import
import
/*
*
*
*
*
*
*
*
*
*
*
Autor:
Holger Rohde
Version: 0.3
1 addiert damit die
werden koennen.
Erzeugung mit
java.awt.GridLayout;
java.awt.event.AdjustmentListener;
javax.swing.JLabel;
javax.swing.JPanel;
javax.swing.JScrollBar;
Erweiterung der Klasse JPanel. Das so erzeugte Panel enthaelt eine
ScrollBar und ein Label fuer die Beschriftung. Die wichtigsten
Methoden der ScrollBar werden durch eigene Methoden nach Aussen
weitergegeben. Methoden zum Setzen und Abfragen von Gleitkommazahlen
werden ergaenzt.
oeffentliche Daten:
---------------------keine
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 85 von 98
*
* private Daten:
* ---------------------*
* serialVersionUID - Da JPanel das Interace Serializable
*
implementiert ist diese Variable notwendig (hat
*
hier aber keine weitere Funktion)
* MIN_DEF
- Standard Minimum der ScrollBar
* MAX_DEF
- Standard Maximum der ScrollBar
* EXT_DEF
- Standard Schrittweite der ScrollBar
* bar
- Die interne ScrollBar
*
* oeffentliche Methoden:
* ---------------------*
* addAdjustmentListener
- Listener zur internen ScrollBar
*
hinzufuegen
* removeAdjustmentListener - Listener von der internen ScrollBar
*
entfernen
* getValue
- Wert der internen ScrollBar zurueckgeben
* setValue
- Wert der internen ScrollBar setzen
* getFloatValue
* setFloatValue
* updateToolTip
- Setzen des ToolTip der internen ScrollBar
* setEnabled
- Aktivieren oder Deaktivieren der internen
*
ScrollBar
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class ExtScrollBar extends JPanel
{
private static int MIN_DEF = 0;
private static int MAX_DEF = 100;
private static int EXT_DEF = 1;
/* JPanel implementiert Serializable
private static final long serialVersionUID = 1;
private JScrollBar bar = null;
*/
public ExtScrollBar (String name, int val, int ext, int min, int max)
{
/* max + 1 da ansonsten nur max - 1 eingestellt werden koennte
*/
bar = new JScrollBar (JScrollBar.HORIZONTAL, val, ext, min,
max + 1);
JLabel label = new JLabel (name);
GridLayout grid = new GridLayout (1, 2);
this.updateToolTip ();
this.setLayout (grid);
this.add (label);
this.add (bar);
}
public ExtScrollBar (String name, int value)
{
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 86 von 98
this (name, value, EXT_DEF, MIN_DEF, MAX_DEF);
}
public ExtScrollBar (String name, int value, int min, int max)
{
this (name, value, EXT_DEF, min, max);
}
public void addAdjustmentListener (AdjustmentListener listener)
{
bar.addAdjustmentListener (listener);
}
public void removeAdjustmentListener (AdjustmentListener listener)
{
bar.removeAdjustmentListener (listener);
}
public int getValue ()
{
return bar.getValue ();
}
public void setValue (int val)
{
bar.setValue (val);
bar.setToolTipText (String.valueOf (val));
}
/*
* Zurueckgeben des aktuellen Werts der ScrollBar als Gleitkommazahl
* nach Umrechnung anhand des uebergebenen Faktors.
*
* Eingabeparameter: int factor
* Ausgabeparameter: float value
* Fehlerausgaenge:
*/
public float getFloatValue (int factor)
{
float value = ((float) bar.getValue ()) / factor;
return value;
}
/*
* Setzen der ScrollBar auf die uebergebene Gleitkommazahl nach
* Umrechnung zur Ganzzahl anhand des Faktors.
*
* Eingabeparameter: int factor, float value
* Ausgabeparameter: * Fehlerausgaenge:
*/
public void setFloatValue (int factor, float value)
{
int val = (int) (value * factor);
bar.setValue (val);
bar.setToolTipText (String.valueOf (val));
}
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 87 von 98
public void updateToolTip ()
{
bar.setToolTipText (String.valueOf (bar.getValue ()));
}
public void setEnabled (boolean val)
{
bar.setEnabled (val);
}
}
5.2.4.4 FlockList.java
/*
* Klasse(n):
FlockList
* Bemerkungen: *
* Datei:
FlockList.java
Autor:
Holger Rohde
* Datum:
03.11.05
Version: 0.3
*
* Historie:
*
* 23.12.05 - Hinzufuegen der Methode "public FlockThr getFlockThr
*
(int index)" fuer die paralle Berechnung der Simulation.
* 17.11.05 - Fehlerbehandlung in den Methoden ergaenzt.
*/
package util;
import java.util.ArrayList;
import ani.FlockSeq;
import ani.FlockThr;
/*
* Erweiterung der Klasse ArrayList zur Ablage von Objekten vom Typ
* FlockSeq und FlockThr.
*
* oeffentliche Daten:
* ---------------------*
* keine
*
* private Daten:
* ---------------------*
* serialVersionUID - Da ArrayList das Interace Serializable
*
implementiert ist diese Variable notwendig (hat
*
hier aber keine weitere Funktion)
*
* oeffentliche Methoden:
* ---------------------*
* getFlock
* getFlockThr
*
* private Methoden:
* ---------------------*
* keine
*
*/
Holger Rohde
WS 2005/2006
Seite 88 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
public class FlockList extends ArrayList
{
/* ArrayList implementiert Serializable
private static final long serialVersionUID = 1;
*/
/*
* Rueckgabe des Elements an der Stelle i und Typumwandlung zu
* FlockSeq.
*
* Eingabeparameter: int index
* Ausgabeparameter: FlockSeq ret
* Fehlerausgaenge:
ArrayIndexOutOfBoundsException
*/
public FlockSeq getFlock (int index)
{
FlockSeq ret = null;
try
{
ret = (FlockSeq) get (index);
}
catch (ArrayIndexOutOfBoundsException e)
{
e.printStackTrace ();
};
return ret;
}
/*
* Rueckgabe des Elements an der Stelle i und Typumwandlung zu
* FlockThr.
*
* Eingabeparameter: int index
* Ausgabeparameter: FlockThr ret
* Fehlerausgaenge:
ArrayIndexOutOfBoundsException
*/
public FlockThr getFlockThr (int index)
{
FlockThr ret = null;
try
{
ret = (FlockThr) get (index);
}
catch (ArrayIndexOutOfBoundsException e)
{
e.printStackTrace ();
};
return ret;
}
}
5.2.4.5 ParameterSet.java
/*
*
*
*
*
*
*
Klasse(n):
ParameterSet
Bemerkungen: Datei:
Datum:
Holger Rohde
ParameterSet.java
06.12.05
Autor:
Holger Rohde
Version: 0.3
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 89 von 98
* Historie:
*
* 10.12.05 - Methode "public String toString ()" zur Ausgabe der
*
aktuellen Werte ueberschrieben.
* 07.12.05 - Implementierung des Interface Cloneable.
*/
package util;
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Zusammenfassung der fuer die Berechnung des Schwarmverhaltens
benoetigten Daten um einen einfacheren Austausch von Aenderungen
zwischen den Kontrollelementen und den Animationsklassen zu
Ermoeglichen.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------birdCount
maxSpeed
maxForce
- Anzahl der Voegel
- Maximale Geschwindigkeit eines Vogels
- Maximale Kraft die in einer Iteration auf einen Vogel
wirken kann
cohAngle
- Blickwinkel des Vogels fuer Kraft "cohesion"
sepAngle
- Blickwinkel des Vogels fuer Kraft "seperation"
alignAngle
- Blickwinkel des Vogels fuer Kraft "alignment"
cohDistance
- Distanz zu den Nachbarvoegeln fuer Kraft
"cohesion"
sepDistance
- Distanz zu den Nachbarvoegeln fuer Kraft
"seperation"
alignDistance - Distanz zu den Nachbarvoegeln fuer Kraft
"alignment"
cohStrength
- Staerke der Kraft "cohesion"
sepStrength
- Staerke der Kraft "seperation"
aliStrength
- Staerke der Kraft "alignment"
oeffentliche Methoden:
---------------------clone
toString
getAlignAngleCos
getCohAngleCos
getSepAngleCos
Getter / Setter:
getAlignAngle
setAlignAngle
getAlignDistance
setAlignDistance
getAliStrength
setAliStregth
getBirdCount
setBirdCount
getCohAngle
setCohAngle
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 90 von 98
* getCohDistance
* setCohDistance
* getCohStrength
* setCohStrength
* getMaxForce
* setMaxForce
* getMaxSpeed
* setMaxSpeed
* getSepAngle
* setSepAngle
* getSepDistance
* setSepDistance
* getSepStrength
* setSepStrength
*
* private Methoden:
* ---------------------*
* keine
*
*/
public class ParameterSet implements Cloneable
{
private int birdCount = AppSetup.bird_count;
private float maxSpeed = AppSetup.speed_def;
private float maxForce = AppSetup.force_def;
private float cohAngle = AppSetup.COH_ANGLE_DEF;
private float sepAngle = AppSetup.SEP_ANGLE_DEF;
private float alignAngle = AppSetup.ALIGN_ANGLE_DEF;
private float cohDistance = AppSetup.COH_DISTANCE_DEF;
private float sepDistance = AppSetup.SEP_DISTANCE_DEF;
private float alignDistance = AppSetup.ALIGN_DISTANCE_DEF;
private float cohStrength = AppSetup.COH_STRENGTH_DEF;
private float sepStrength = AppSetup.SEP_STRENGTH_DEF;
private float aliStrength = AppSetup.ALIGN_STRENGTH_DEF;
/*
* Implementierung aus Interface Cloneable zur Erzeugung einer Kopie
* der Klasse.
*
* Eingabeparameter: * Ausgabeparameter: Object clone
* Fehlerausgaenge: */
public Object clone () throws CloneNotSupportedException
{
Object clone = super.clone ();
return clone;
}
/*
* Darstellung der Klassenvariablen als Zeichenkette durch
* Ueberschreiben der Methode in Klasse Object.
*
* Eingabeparameter: * Ausgabeparameter: String string
* Fehlerausgaenge:
*/
public String toString ()
{
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 91 von 98
StringBuffer string = new StringBuffer ();
string.append
string.append
string.append
string.append
string.append
string.append
string.append
string.append
string.append
string.append
string.append
string.append
string.append
string.append
("------------ParameterSet------------\n");
("birdCount:
" + birdCount + "\n");
("maxSpeed:
" + maxSpeed + "\n");
("maxForce:
" + maxForce + "\n");
("cohAngle:
" + cohAngle + "\n");
("sepAngle:
" + sepAngle + "\n");
("alignAngle:
" + alignAngle + "\n");
("cohDistance:
" + cohDistance + "\n");
("sepDistance:
" + sepDistance + "\n");
("alignDistance: " + alignDistance + "\n");
("cohStrength:
" + cohStrength + "\n");
("sepStrength:
" + sepStrength + "\n");
("aliStrength:
" + aliStrength + "\n");
("------------------------------------\n");
return string.toString ();
}
public float getAlignAngle ()
{
return alignAngle;
}
public void setAlignAngle (float alignAngle)
{
this.alignAngle = alignAngle;
}
/*
* Cosinus von alignAngle bestimmen und zurueckgeben.
*
* Eingabeparameter: * Ausgabeparameter: float alignAngleCos
* Fehlerausgaenge:
*/
public float getAlignAngleCos ()
{
/* Umrechnung in Bogenmass und Ermitteln des Cosinus
float alignAngleCos = (float) Math.cos (
(alignAngle / 180F) * Math.PI);
*/
return alignAngleCos;
}
public float getAlignDistance ()
{
return alignDistance;
}
public void setAlignDistance (float alignDistance)
{
this.alignDistance = alignDistance;
}
public float getAliStrength ()
{
return aliStrength;
}
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 92 von 98
public void setAliStrength (float aliStrength)
{
this.aliStrength = aliStrength;
}
public int getBirdCount ()
{
return birdCount;
}
public void setBirdCount (int birdCount)
{
this.birdCount = birdCount;
}
public float getCohAngle ()
{
return cohAngle;
}
public void setCohAngle (float cohAngle)
{
this.cohAngle = cohAngle;
}
/*
* Cosinus von cohAngle bestimmen und zurueckgeben.
*
* Eingabeparameter: * Ausgabeparameter: float cohAngleCos
* Fehlerausgaenge:
*/
public float getCohAngleCos ()
{
/* Umrechnung in Bogenmass und Ermitteln des Cosinus
float cohAngleCos = (float) Math.cos (
(cohAngle / 180F) * Math.PI);
*/
return cohAngleCos;
}
public float getCohDistance ()
{
return cohDistance;
}
public void setCohDistance (float cohDistance)
{
this.cohDistance = cohDistance;
}
public float getCohStrength ()
{
return cohStrength;
}
public void setCohStrength (float cohStrength)
{
this.cohStrength = cohStrength;
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 93 von 98
}
public float getMaxForce ()
{
return maxForce;
}
public void setMaxForce (float maxForce)
{
this.maxForce = maxForce;
}
public float getMaxSpeed ()
{
return maxSpeed;
}
public void setMaxSpeed (float maxSpeed)
{
this.maxSpeed = maxSpeed;
}
public float getSepAngle ()
{
return sepAngle;
}
public void setSepAngle (float sepAngle)
{
this.sepAngle = sepAngle;
}
/*
* Cosinus von sepAngle bestimmen und zurueckgeben.
*
* Eingabeparameter: * Ausgabeparameter: float sepAngleCos
* Fehlerausgaenge:
*/
public float getSepAngleCos ()
{
/* Umrechnung in Bogenmass und Ermitteln des Cosinus
float sepAngleCos = (float) Math.cos (
(sepAngle / 180F) * Math.PI);
*/
return sepAngleCos;
}
public float getSepDistance ()
{
return sepDistance;
}
public void setSepDistance (float sepDistance)
{
this.sepDistance = sepDistance;
}
public float getSepStrength ()
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 94 von 98
{
return sepStrength;
}
public void setSepStrength (float sepStrength)
{
this.sepStrength = sepStrength;
}
}
5.2.4.6 Timer.java
/*
* Klasse(n):
Timer
* Bemerkungen: Nutzt die JAMon-Bibliothek aus "lib/JAMon.jar".
*
* Datei:
Timer.java
Autor:
Holger Rohde
* Datum:
18.12.05
Version: 0.2
*
* Historie:
*
* 25.12.05 - Methode "public void print ()" zur Ausgabe der aktuellen
*
Werte der Messung hinzugefuegt.
*/
package util;
import java.util.StringTokenizer;
import com.jamonapi.Monitor;
import com.jamonapi.MonitorFactory;
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Implementierung einer Zeitmessung unter Verwendung der Bibliothek
JAMon (http://jamonapi.com/). Es werden Methoden zum Starten und
Stoppen der Zeitmessung und den Zugriff auf die Ergebnisse zur
Verfuegung gestellt. Die durch die Bibliotheksfunktionen gelieferten
Ergebnisse werden an die Anforderungen des Programms angepasst.
oeffentliche Daten:
---------------------keine
private Daten:
---------------------monitor - Instanz der Monitor-Klasse aus Bibliothek JAMon ueber die
die Zeitmessung realisiert wird
time
- Zeit der letzen Messung
avg
- Durchschnittszeit aller Messsungen
hits
- Anzahl der durchgefuehrten Messungen
total
- Gesamtzeit aller durchgefuehrten Messungen
oeffentliche Methoden:
----------------------
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 95 von 98
*
* start
* stop
* print
*
* Getter / Setter:
*
* getAvg
* getHits
* getTime
* getTotal
*
* private Methoden:
* ---------------------*
* getTokens
*
*/
public class Timer
{
private Monitor monitor = null;
private String time = "";
private String avg = "";
private String hits = "";
private String total = "";
/*
* Starten der Zeitmessung. Durch den ersten Aufruf wird eine neue
* Instanz der Klasse Monitor erzeugt. Weitere Aufrufe nutzen die alte
* Instanz.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void start ()
{
monitor = MonitorFactory.start ("monitor");
}
/*
* Stoppen der Zeitmessung und Aufruf der internen Ergebissanpassung.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void stop ()
{
monitor.stop ();
this.getTokens ();
}
/*
*
*
*
*
*
*
Auslesen der relevanten Werte des Monitor-Objekt und Aktualisierung
der entsprechenden Variablen. Die Ergebnisse liegen als
Zeichenkette vor und werden mit der Klasse StringTokenizer zerlegt.
Eingabeparameter:
Ausgabeparameter:
Holger Rohde
-
WS 2005/2006
Seite 96 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
* Fehlerausgaenge:
*/
private void getTokens ()
{
StringTokenizer tok = new StringTokenizer (monitor.toString ());
time = tok.nextToken ();
tok.nextToken ();
hits = tok.nextToken ();
hits = hits.substring (6);
avg = tok.nextToken ();
avg = avg.substring (4);
tok.nextToken ();
total = tok.nextToken ();
total = total.substring (6);
/* Ueberspringen eines Tokens */
/* Ueberspringen eines Tokens */
}
/*
* Ausgabe der aktuellen Messwerte und der Vogel- und Schwarmanzahl
* auf die Konsole.
*
* Eingabeparameter: * Ausgabeparameter: * Fehlerausgaenge:
*/
public void print ()
{
System.out.print (AppSetup.bird_count + "\t");
System.out.print (AppSetup.flock_count + "\t");
System.out.print (avg + "\t");
System.out.print (total + "\t");
System.out.println (hits);
}
public String getAvg ()
{
return avg;
}
public String getHits ()
{
return hits;
}
public String getTime ()
{
return time;
}
public String getTotal ()
{
return total;
}
}
5.2.5 Skripte zum Übersetzen und Ausführen
5.2.5.1 benchmark.bat
::Tests ohne Threads
Holger Rohde
WS 2005/2006
Seite 97 von 98
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
java
java
java
java
java
java
java
-cp
-cp
-cp
-cp
-cp
-cp
-cp
lib/JAMon.jar;bin
lib/JAMon.jar;bin
lib/JAMon.jar;bin
lib/JAMon.jar;bin
lib/JAMon.jar;bin
lib/JAMon.jar;bin
lib/JAMon.jar;bin
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
-t
-t
-t
-t
-t
-t
-t
-f3
-f3
-f3
-f3
-f3
-f3
-f3
-b10 > bench.log
-b20 >> bench.log
-b40 >> bench.log
-b80 >> bench.log
-b160 >> bench.log
-b320 >> bench.log
-b640 >> bench.log
::Tests mit je einem Thread pro Schwarm
java -cp lib/JAMon.jar;bin gui.MainFrame
java -cp lib/JAMon.jar;bin gui.MainFrame
java -cp lib/JAMon.jar;bin gui.MainFrame
java -cp lib/JAMon.jar;bin gui.MainFrame
java -cp lib/JAMon.jar;bin gui.MainFrame
java -cp lib/JAMon.jar;bin gui.MainFrame
java -cp lib/JAMon.jar;bin gui.MainFrame
-t
-t
-t
-t
-t
-t
-t
-f3
-f3
-f3
-f3
-f3
-f3
-f3
-b10 -p > bench_thr.log
-b20 -p >> bench_thr.log
-b40 -p >> bench_thr.log
-b80 -p >> bench_thr.log
-b160 -p >> bench_thr.log
-b320 -p >> bench_thr.log
-b640 -p >> bench_thr.log
5.2.5.2 benchmark.sh
#/bin/sh
#Tests ohne Threads
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
-t
-t
-t
-t
-t
-t
-t
-f3
-f3
-f3
-f3
-f3
-f3
-f3
-b10 > bench.log
-b20 >> bench.log
-b40 >> bench.log
-b80 >> bench.log
-b160 >> bench.log
-b320 >> bench.log
-b640 >> bench.log
#Tests mit je einem Thread
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
java -cp lib/JAMon.jar:bin
pro Schwarm
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
gui.MainFrame
-t
-t
-t
-t
-t
-t
-t
-f3
-f3
-f3
-f3
-f3
-f3
-f3
-b10 -p > bench_thr.log
-b20 -p >> bench_thr.log
-b40 -p >> bench_thr.log
-b80 -p >> bench_thr.log
-b160 -p >> bench_thr.log
-b320 -p >> bench_thr.log
-b640 -p >> bench_thr.log
5.2.5.3 compile.bat
::Uebersetzen der Anwendung
::alle Warnungen aktiviert
javac -Xlint:all -target 1.4 -source 1.4 -cp lib/JAMon.jar;src -d bin
src/i18n/*.java src/util/*.java src/gui/*.java src/ani/*.java
::Die Internationalisierungsdateien muessen manuell kopiert werden
copy /y src\i18n\*.properties bin\i18n
pause
5.2.5.4 compile.sh
#/bin/sh
#Uebersetzen der Anwendung
#alle Warnungen aktiviert
javac -Xlint:all -target 1.4 -source 1.4 -cp lib/JAMon.jar:src -d bin
src/i18n/*.java src/util/*.java src/gui/*.java src/ani/*.java
Holger Rohde
WS 2005/2006
Error! Use the Home tab to apply
Überschrift 1 to the text that you want to
appear here.
Seite 98 von 98
#Die Internationalisierungsdateien muessen manuell kopiert werden
cp src/i18n/*.properties bin/i18n
5.2.5.5 run.bat
::
::
::
::
::
::
::
::
::
::
::
::
::
Moegliche Argumente:
-d Ausgabe von Statusmeldungen
-b
Anzahl der Voegel z.B. -b40
-t
Testmodus zur Leistungsmessung
-p Anwendung nutzt einen Thread pro Schwarm
-f Anzahl der Schwaerme z.B. -f3
Beispiel (3 Schwaerme mit jeweils 50 Voegeln und ein Thread pro Schwarm):
java -cp lib/JAMon.jar;bin gui.MainFrame -p -f3 -b50
java -cp lib/JAMon.jar;bin gui.MainFrame
5.2.5.6 run.sh
#
#
#
#
#
#
#
#
#
#
#
#
#
Moegliche Argumente:
-d
-b
-t
-p
-f
Ausgabe von Statusmeldungen
Anzahl der Voegel z.B. -b40
Testmodus zur Leistungsmessung
Anwendung nutzt einen Thread pro Schwarm
Anzahl der Schwaerme z.B. -f3
Beispiel (3 Schwaerme mit jeweils 50 Voegeln und ein Thread pro Schwarm):
java -cp lib/JAMon.jar;bin gui.MainFrame -p -f3 -b50
java -cp lib/JAMon.jar:bin gui.MainFrame
Holger Rohde
WS 2005/2006
Herunterladen