mirror of
https://codeberg.org/qg-info-unterricht/zpg-graphentester.git
synced 2026-03-24 20:48:26 +01:00
First Commit (Fobi)
This commit is contained in:
commit
2bff291a51
336 changed files with 88781 additions and 0 deletions
139
graph/Graph.ctxt
Normal file
139
graph/Graph.ctxt
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#BlueJ class context
|
||||
comment0.target=Graph
|
||||
comment0.text=\r\n\ Dies\ ist\ das\ Herz\ vom\ "GraphTester"\ -\ der\ Graph\ selber,\ gepeichert\ als\ Adjazenzliste.\r\n\ Die\ Klasse\ erlaubt\ durch\ geeignete\ Methoden\:\r\n\ -\ die\ Speicherung\ als\ Adjazenzmatrix,\r\n\ -\ das\ Hinzufuegen\ und\ Loeschen\ von\ knoten\ und\ Kanten,\r\n\ -\ das\ Markieren\ von\ Knoten\ und\ Kanten,\r\n\ -\ eine\ Aussage\ darueber,\ ob\ Knoten\ oder\ Kanten\ enthalten\ sind\ und\r\n\ -\ eine\ Ausgabe\ des\ Graphen\ in\ textueller\ Form\ sowie\ als\ csv-Datei.\r\n\ \r\n\ \r\n\ @author\ Dirk\ Zechnall,\ Thomas\ Schaller\r\n\ @version\ 31.01.2021\ (v6.5)\r\n
|
||||
comment1.params=isGerichtet\ isGewichtet
|
||||
comment1.target=Graph(boolean,\ boolean)
|
||||
comment1.text=\r\n\ Der\ Konstruktor\ erstellt\ einen\ neuen\ Graphen\ (genauer\ eine\ neue\ Adjazenzliste)\r\n\ @param\ isGerichtet\ gibt\ an,\ ob\ es\ sich\ um\ einen\ gerichteten\ Graphen\ handelt\r\n\ @param\ isGewichtet\ gibt\ an,\ ob\ die\ Kanten\ gewichtet\ sind.\r\n
|
||||
comment10.params=k
|
||||
comment10.target=int\ getNummer(Kante)
|
||||
comment10.text=\ Gibt\ die\ Nummer\ einer\ Kante\ zur\u00FCck\r\n\ @param\ \ k\ gesuchte\ Kante\r\n\ @return\ Nummer\ der\ Kante\ (mit\ 0\ beginnend)\r\n
|
||||
comment11.params=
|
||||
comment11.target=double[][]\ getAdjazenzMatrix()
|
||||
comment11.text=\r\n\ Die\ Methode\ getAdjazenzMatrix()\ gibt\ die\ Adjazenzmatrix\ zurueck.\r\n\ \r\n\ @return\ \ double[][]\ Die\ AdjazenzMatrix\ als\ zweidimensionales\ Array\r\n
|
||||
comment12.params=filter
|
||||
comment12.target=java.util.List\ getAlleKanten(java.util.function.Predicate[])
|
||||
comment12.text=\r\n\ Gibt\ eine\ Liste\ aller\ Kanten\ des\ Graphen\ zur\u00FCck.\r\n\ @param\ \ \ filter\ \ \ \ \ \ \ \ \ optionaler\ Filter,\ der\ auf\ die\ Liste\ angewendet\ wird.\ Er\ muss\ einen\ boolean-Wert\ zur\u00FCckgeben\:\ z.B.\ @literal{k->k.isMarkiert()\ &&\ k.isBesucht()}\r\n\ @return\ Liste\ aller\ Kanten\r\n
|
||||
comment13.params=
|
||||
comment13.target=void\ entferneMarkierungBeiAllenKnoten()
|
||||
comment13.text=\r\n\ Entfernt\ die\ Markierung\ bei\ allen\ Knoten\ des\ Graphen.\r\n
|
||||
comment14.params=
|
||||
comment14.target=void\ initialisiereAlleKnoten()
|
||||
comment14.text=\r\n\ Initialisiert\ alle\ Knoten\ des\ Graphen.\r\n
|
||||
comment15.params=
|
||||
comment15.target=void\ initialisiereAlleKanten()
|
||||
comment15.text=\r\n\ Initialisiert\ alle\ Kanten\ des\ Graphen.\r\n
|
||||
comment16.params=k
|
||||
comment16.target=boolean\ isKnotenEnthalten(Knoten)
|
||||
comment16.text=\r\n\ Ueberprueft,\ ob\ ein\ Knoten\ in\ der\ Knotenliste\ enthalten\ ist.\r\n\ Sobald\ in\ der\ Knotenliste\ der\ Knoten\ k\ gefunden\ wird,\ wird\ true\ ausgegeben.\r\n\ \r\n\ @param\ \ k\ \ Der\ gesuchte\ Knoten\r\n\ @return\ \ true\=\ ist\ enthalten,\ false\ \=\ ist\ nicht\ enthalten\r\n
|
||||
comment17.params=
|
||||
comment17.target=int\ getAnzahlKnoten()
|
||||
comment17.text=\r\n\ Gibt\ die\ Anzahl\ der\ Knoten\ im\ Graph\ zurueck\r\n\ \r\n\ @return\ \ Anzahl\ der\ Knoten\r\n
|
||||
comment18.params=filter
|
||||
comment18.target=java.util.List\ getAlleKnoten(java.util.function.Predicate[])
|
||||
comment18.text=\r\n\ Gibt\ eine\ Liste\ aller\ Knoten\ des\ Graphen\ zurueck.\ \r\n\ @param\ \ \ filter\ \ \ \ \ \ \ \ \ optionaler\ Filter,\ der\ auf\ die\ Liste\ angewendet\ wird.\ Er\ muss\ einen\ boolean-Wert\ zur\u00FCckgeben\:\ z.B.\ @literal{k->k.isMarkiert()\ &&\ k.isBesucht()}\r\n\ @return\ \ Die\ Knotenliste.\ Falls\ leer\ wird\ eine\ leere\ Liste\ \ zurueckgegeben\r\n
|
||||
comment19.params=k\ filter
|
||||
comment19.target=java.util.List\ getNachbarknoten(Knoten,\ java.util.function.Predicate[])
|
||||
comment19.text=\r\n\ Gibt\ die\ Liste\ aller\ Nachbarknoten\ eines\ Knotens\ k\ zurueck,\ falls\ k\ in\ der\ Knotenliste\ vorhanden\ ist.\ \r\n\r\n\ @param\ \ \ k\ \ \ \ Der\ Knoten,\ zu\ dem\ die\ Adjazenzliste\ gesucht\ wird\r\n\ @param\ \ \ filter\ \ \ \ \ \ \ \ \ optionaler\ Filter,\ der\ auf\ die\ Liste\ angewendet\ wird.\ Er\ muss\ einen\ boolean-Wert\ zur\u00FCckgeben\:\ z.B.\ @literal{k->k.isMarkiert()\ &&\ k.isBesucht()}\r\n\ @return\ \ Liste\ der\ Nachbarknoten\r\n
|
||||
comment2.params=
|
||||
comment2.target=Graph()
|
||||
comment2.text=\r\n\ Der\ Konstruktor\ erstellt\ einen\ neuen\ ungerichteten,\ ungewichteten\ Graphen\ (genauer\ eine\ neue\ Adjazenzliste)\r\n
|
||||
comment20.params=k\ filter
|
||||
comment20.target=java.util.List\ getAusgehendeKanten(Knoten,\ java.util.function.Predicate[])
|
||||
comment20.text=\r\n\ Gibt\ eine\ Liste\ der\ ausgehenden\ Kanten\ eines\ Knotens\ k\ zurueck,\ falls\ k\ in\ der\ Knotenliste\ vorhanden\ ist.\ \r\n\ Bei\ ungerichteten\ Graphen\ wird\ nicht\ zwischen\ eingehenden\ und\ ausgehenden\ Kanten\ \r\n\ unterschieden.\r\n\r\n\ @param\ \ \ k\ \ \ \ Der\ Knoten,\ zu\ dem\ die\ Kanten\ gesucht\ werden\r\n\ @param\ \ \ filter\ \ \ \ \ \ \ \ \ optionaler\ Filter,\ der\ auf\ die\ Liste\ angewendet\ wird.\ Er\ muss\ einen\ boolean-Wert\ zur\u00FCckgeben\:\ z.B.\ @literal{k->k.isMarkiert()\ &&\ k.isBesucht()}\r\n\ @return\ \ Liste\ der\ ausgehenden\ Kanten.\r\n
|
||||
comment21.params=knotennr\ filter
|
||||
comment21.target=java.util.List\ getAusgehendeKanten(int,\ java.util.function.Predicate[])
|
||||
comment21.text=\r\n\ Gibt\ eine\ Liste\ der\ ausgehenden\ Kanten\ eines\ Knotens\ k\ zurueck,\ falls\ k\ in\ der\ Knotenliste\ vorhanden\ ist.\ \r\n\ Bei\ ungerichteten\ Graphen\ wird\ nicht\ zwischen\ eingehenden\ und\ ausgehenden\ Kanten\ \r\n\ unterschieden.\r\n\r\n\ @param\ \ \ knotennr\ \ \ \ Nummer\ des\ Knoten,\ zu\ dem\ die\ Kanten\ gesucht\ werden\r\n\ @param\ \ \ filter\ \ \ \ \ \ \ \ \ optionaler\ Filter,\ der\ auf\ die\ Liste\ angewendet\ wird.\ Er\ muss\ einen\ boolean-Wert\ zur\u00FCckgeben\:\ z.B.\ @literal{k->k.isMarkiert()\ &&\ k.isBesucht()}\r\n\ @return\ \ Liste\ der\ ausgehenden\ Kanten.\r\n
|
||||
comment22.params=knotennr\ filter
|
||||
comment22.target=java.util.List\ getEingehendeKanten(int,\ java.util.function.Predicate[])
|
||||
comment22.text=\r\n\ Gibt\ eine\ Liste\ der\ eingehenden\ Kanten\ eines\ Knotens\ k\ zurueck,\ falls\ k\ in\ der\ Knotenliste\ vorhanden\ ist.\ \r\n\ Bei\ ungerichteten\ Graphen\ wird\ nicht\ zwischen\ eingehenden\ und\ ausgehenden\ Kanten\ \r\n\ unterschieden.\r\n\r\n\ @param\ \ \ knotennr\ \ \ \ Die\ Nummer\ des\ Knotens,\ zu\ dem\ die\ Kanten\ gesucht\ werden\r\n\ @param\ \ \ filter\ \ \ \ \ \ optionaler\ Filter,\ der\ auf\ die\ Liste\ angewendet\ wird.\ Er\ muss\ einen\ boolean-Wert\ zur\u00FCckgeben\:\ z.B.\ @literal{k->k.isMarkiert()\ &&\ k.isBesucht()}\r\n\ @return\ \ Liste\ der\ eingehenden\ Kanten.\r\n
|
||||
comment23.params=k\ filter
|
||||
comment23.target=java.util.List\ getEingehendeKanten(Knoten,\ java.util.function.Predicate[])
|
||||
comment23.text=\r\n\ Gibt\ eine\ Liste\ der\ eingehenden\ Kanten\ eines\ Knotens\ k\ zurueck,\ falls\ k\ in\ der\ Knotenliste\ vorhanden\ ist.\ \r\n\ Bei\ ungerichteten\ Graphen\ wird\ nicht\ zwischen\ eingehenden\ und\ ausgehenden\ Kanten\ \r\n\ unterschieden.\r\n\r\n\ @param\ \ \ k\ \ \ \ \ \ \ \ Knoten,\ zu\ dem\ die\ Kanten\ gesucht\ werden\r\n\ @param\ \ \ filter\ \ \ optionaler\ Filter,\ der\ auf\ die\ Liste\ angewendet\ wird.\ Er\ muss\ einen\ boolean-Wert\ zur\u00FCckgeben\:\ z.B.\ @literal{k->k.isMarkiert()\ &&\ k.isBesucht()}\r\n\ @return\ \ Liste\ der\ eingehenden\ Kanten.\r\n
|
||||
comment24.params=knotennr
|
||||
comment24.target=Knoten\ getKnoten(int)
|
||||
comment24.text=\r\n\ Liefert\ einen\ Knoten\ des\ Graphen\r\n\ @param\ knotennr\ Nummer\ der\ Knoten\ (beginnend\ mit\ 0)\r\n\ @return\ liefert\ den\ Knoten\ mit\ dieser\ Nummer\r\n
|
||||
comment25.params=k
|
||||
comment25.target=void\ neuerKnoten(Knoten)
|
||||
comment25.text=\r\n\ F\u00FCgt\ einen\ Knoten\ dem\ Graph\ hinzu.\r\n\ @param\ \ k\ \ \ \ Der\ Knoten,\ der\ hinzugefuegt\ werden\ soll\r\n
|
||||
comment26.params=knotennr
|
||||
comment26.target=void\ entferneKnoten(int)
|
||||
comment26.text=\r\n\ Entfernt\ einen\ Knoten\ aus\ dem\ Graphen\r\n\r\n\ @param\ \ \ knotennr\ \ \ \ Nummer\ des\ Knotens,\ der\ geloescht\ werden\ soll\r\n
|
||||
comment27.params=k
|
||||
comment27.target=boolean\ entferneKnoten(Knoten)
|
||||
comment27.text=\r\n\ Entfernt\ einen\ Knoten\ aus\ dem\ Graphen\r\n\r\n\ @param\ \ \ k\ \ \ \ Knoten,\ der\ geloescht\ werden\ soll\r\n\ @return\ \ gibt\ zur\u00FCck,\ ob\ der\ Knoten\ erfolgreich\ entfernt\ wurde.\r\n
|
||||
comment28.params=e
|
||||
comment28.target=boolean\ isKanteEnthalten(Kante)
|
||||
comment28.text=\r\n\ Ueberprueft,\ ob\ eine\ Kante\ im\ Graphen\ enthalten\ ist.\r\n\r\n\ @param\ \ \ e\ \ \ \ \ Die\ zu\ suchende\ Kante\r\n\ @return\ \ Kante\ enthalten\ (true)\ oder\ nicht\ (false)\r\n
|
||||
comment29.params=startNr\ zielNr
|
||||
comment29.target=boolean\ isKanteEnthalten(int,\ int)
|
||||
comment29.text=\r\n\ Ueberprueft,\ ob\ eine\ Kante\ im\ Graphen\ enthalten\ ist.\ \r\n\ In\ ungerichteten\ Graphen\ wird\ nicht\ zwischen\ Start-\ und\ Zielknoten\ unterschieden\r\n\r\n\ @param\ \ \ startNr\ \ \ \ Nummer\ des\ Startknotens\r\n\ @param\ \ \ zielNr\ \ \ \ \ Nummer\ des\ Zielknotens\r\n\ @return\ \ boolean\ \ \ \ \ Kante\ enthalten\ (true)\ oder\ nicht\ (false)\r\n
|
||||
comment3.params=
|
||||
comment3.target=void\ loescheGraph()
|
||||
comment3.text=\r\n\ L\u00F6scht\ alle\ Knoten\ und\ Kanten\ eines\ Graphen\ und\ stellt\ auf\ ungerichtet\ und\ ungewichtet\ zur\u00FCck.\r\n
|
||||
comment30.params=start\ ziel
|
||||
comment30.target=boolean\ isKanteEnthalten(Knoten,\ Knoten)
|
||||
comment30.text=\r\n\ Ueberprueft,\ ob\ eine\ Kante\ im\ Graphen\ enthalten\ ist.\ \r\n\ In\ ungerichteten\ Graphen\ wird\ nicht\ zwischen\ Start-\ und\ Zielknoten\ unterschieden\r\n\r\n\ @param\ \ \ start\ \ \ \ Startknoten\r\n\ @param\ \ \ ziel\ \ \ \ \ Zielknoten\r\n\ @return\ \ boolean\ \ \ \ \ Kante\ enthalten\ (true)\ oder\ nicht\ (false)\r\n
|
||||
comment31.params=start\ ziel
|
||||
comment31.target=Kante\ getKante(Knoten,\ Knoten)
|
||||
comment31.text=\r\n\ Gibt\ eine\ gesuchte\ Kante\ aus\ dem\ Graphen\ zurueck.\r\n\ In\ ungerichteten\ Graphen\ wird\ nicht\ zwischen\ Start-\ und\ Zielknoten\ unterschieden\r\n\r\n\ @param\ \ \ start\ \ \ \ Der\ StartKnoten\r\n\ @param\ \ \ ziel\ \ \ \ \ Der\ StartKnoten\r\n\ @return\ \ \ \ Die\ gesuchte\ Kante\r\n
|
||||
comment32.params=startnr\ zielnr
|
||||
comment32.target=Kante\ getKante(int,\ int)
|
||||
comment32.text=\r\n\ Gibt\ eine\ gesuchte\ Kante\ aus\ dem\ Graphen\ zurueck.\r\n\ In\ ungerichteten\ Graphen\ wird\ nicht\ zwischen\ Start-\ und\ Zielknoten\ unterschieden\r\n\r\n\ @param\ \ \ startnr\ \ \ \ Der\ Nummer\ des\ StartKnoten\r\n\ @param\ \ \ zielnr\ \ \ \ \ Die\ Nummer\ des\ Zielknoten\r\n\ @return\ \ Die\ gesuchte\ Kante\r\n
|
||||
comment33.params=e
|
||||
comment33.target=void\ neueKante(Kante)
|
||||
comment33.text=\r\n\ Fuegt\ eine\ Kante\ dem\ Graphen\ hinzu.\r\n\ Dabei\ wird\ ueberprueft,\ ob\ die\ Kante\ schon\ im\ Graphen\ enthalten\ ist.\r\n\ \r\n\ Ist\ der\ Graph\ ungerichtet,\ werden\ sowohl\ "Hin-"\ und\ "RueckKante"\ erstellt.\r\n\r\n\ @param\ \ \ e\ \ \ \ \ Die\ Kante,\ die\ hinzugefuegt\ werden\ soll\r\n
|
||||
comment34.params=start\ ziel\ gewicht
|
||||
comment34.target=void\ neueKante(Knoten,\ Knoten,\ double)
|
||||
comment34.text=\r\n\ Fuegt\ eine\ Kante\ dem\ Graphen\ hinzu.\r\n\ Dabei\ wird\ ueberprueft,\ ob\ die\ Kante\ schon\ im\ Graphen\ enthalten\ ist.\r\n\ \r\n\ Ist\ der\ Graph\ ungerichtet,\ werden\ sowohl\ "Hin-"\ und\ "RueckKante"\ erstellt.\r\n\r\n\ @param\ \ \ start\ \ \ \ \ Der\ StartKnoten\ der\ Kante,\ die\ hinzugefuegt\ werden\ soll\r\n\ @param\ \ \ ziel\ \ \ \ \ Der\ ZielKnoten\ der\ Kante,\ die\ hinzugefuegt\ werden\ soll\r\n\ @param\ \ \ gewicht\ \ \ \ \ Das\ Gewicht\ der\ Kante,\ die\ hinzugefuegt\ werden\ soll\r\n
|
||||
comment35.params=e
|
||||
comment35.target=void\ entferneKante(Kante)
|
||||
comment35.text=\r\n\ Entfernt\ eine\ Kante\ aus\ dem\ Graphen.\r\n\ Ist\ der\ Graph\ ungerichtet,\ werden\ sowohl\ "Hin-"\ und\ "RueckKante"\ entfernt.\r\n\r\n\ @param\ \ \ e\ Die\ zu\ entfernende\ Kante\r\n
|
||||
comment36.params=start\ ziel
|
||||
comment36.target=void\ entferneKante(Knoten,\ Knoten)
|
||||
comment36.text=\r\n\ Entfernt\ eine\ Kante\ aus\ dem\ Graphen.\r\n\ Dabei\ wird\ ueberprueft,\ ob\ die\ Kante\ ueberhaupt\ im\ Graphen\ enthalten\ ist.\r\n\ \r\n\ Ist\ der\ Graph\ ungerichtet,\ werden\ sowohl\ "Hin-"\ und\ "RueckKante"\ entfernt.\r\n\r\n\ @param\ \ \ start\ \ \ \ StartKnotens\r\n\ @param\ \ \ ziel\ \ \ \ \ ZielKnotens\r\n
|
||||
comment37.params=startnr\ zielnr
|
||||
comment37.target=void\ entferneKante(int,\ int)
|
||||
comment37.text=\r\n\ Entfernt\ eine\ Kante\ aus\ dem\ Graphen.\r\n\ Ist\ der\ Graph\ ungerichtet,\ werden\ sowohl\ "Hin-"\ und\ "RueckKante"\ entfernt.\r\n\r\n\ @param\ \ \ startnr\ \ \ \ Nummer\ des\ StartKnotens\r\n\ @param\ \ \ zielnr\ \ \ \ \ Nummer\ des\ ZielKnotens\r\n
|
||||
comment38.params=
|
||||
comment38.target=boolean\ isLeer()
|
||||
comment38.text=\r\n\ Ueberprueft,\ ob\ die\ Adjazenzliste\ leer\ ist,\ d.h.\ keine\ Knoten\ im\ Graphen\ enthalten\ sind.\r\n\ \r\n\ @return\ \ \ true,\ wenn\ die\ Liste\ leer\ ist,\ sonst\ false\r\n
|
||||
comment39.params=
|
||||
comment39.target=void\ loescheAlles()
|
||||
comment39.text=\r\n\ Loescht\ den\ gesamten\ Graphen\r\n
|
||||
comment4.params=csvParser
|
||||
comment4.target=boolean\ ladeGraph(imp.Table)
|
||||
comment4.text=\r\n\ Ein\ Graph\ wird\ aus\ einer\ csv-Datei\ erstellt,\ die\ entweder\r\n\ eine\ Matrix\ oder\ eine\ Adjazenzliste\ enth\u00E4lt,\ die\ den\ Graph\ beschreibt.\r\n\r\n\ @param\ \ csvParser\ \ \ Eine\ CSV-Datei\ als\ Table-Objekt\r\n\ @return\ gibt\ zur\u00FCck,\ ob\ das\ Laden\ erfolgreich\ war\r\n
|
||||
comment40.params=asMatrix
|
||||
comment40.target=java.lang.String\ toCSVString(boolean)
|
||||
comment40.text=\r\n\ Die\ Methode\ erstellt\ eine\ CSV-Ausgabe\ des\ Graphen\ entweder\ als\ Adjazenzliste\ oder\ als\ Adjazenzmatrix.\r\n\r\n\ @param\ \ \ asMatrix\ \ \ \ true,\ falls\ die\ CSV-Ausgabe\ eine\ AdjazenzMatrix\ sein\ soll,\ sonst\ false\r\n\ @return\ \ CSV-Ausgabe\r\n
|
||||
comment41.params=
|
||||
comment41.target=java.lang.String\ toString()
|
||||
comment41.text=\r\n\ Textuelle\ Repraesentation\ des\ Graphen.\r\n\ \r\n\ @return\ \ Der\ Graph\ als\ Stringrepraesentation\r\n
|
||||
comment42.params=
|
||||
comment42.target=void\ ausgabe()
|
||||
comment42.text=\r\n\ Konsolenausgabe\ der\ textuellen\ Repraesentation\ des\ Graphen.\r\n
|
||||
comment43.params=k\ zeigeWert
|
||||
comment43.target=java.lang.String\ getKnoteninfo(Knoten,\ boolean)
|
||||
comment43.text=\r\n\ Info\ \u00FCber\ einen\ Knoten\ zur\u00FCckgeben\ \r\n\ @param\ k\ Knoten,\ des\ Info\ ermittelt\ werden\ soll\r\n\ @param\ zeigeWert\ Soll\ der\ Wert\ des\ Knoten\ in\ der\ Info\ enthalten\ sein\r\n\ @return\ Infotext\ oder\ Nummer\ des\ Knoten\ und\ ggf.\ sein\ Wert\r\n
|
||||
comment44.params=
|
||||
comment44.target=java.util.List\ getStatus()
|
||||
comment44.text=\ Speichert\ den\ Zustand\ des\ Graphen\ als\ String-List\r\n\ @return\ List\ mit\ Zustand\r\n
|
||||
comment45.params=status
|
||||
comment45.target=void\ setStatus(java.util.List)
|
||||
comment45.text=\ Stellt\ den\ Zustand\ des\ Graphen\ aus\ String-List\ wieder\ her\r\n\ @param\ status\ List\ mit\ Zustand\r\n
|
||||
comment5.params=isGewichtet
|
||||
comment5.target=void\ setGewichtet(boolean)
|
||||
comment5.text=\r\n\ Legt\ fest,\ ob\ der\ Graph\ gewichtet\ oder\ ungewichtet\ ist.\r\n\r\n\ @param\ isGewichtet\ neuer\ Wert\r\n
|
||||
comment6.params=
|
||||
comment6.target=boolean\ isGewichtet()
|
||||
comment6.text=\r\n\ Gibt\ zurueck,\ ob\ der\ Graph\ gewichtet\ oder\ ungewichtet\ ist\r\n\r\n\ @return\ gewichtet?\ (true/false)\r\n
|
||||
comment7.params=isGerichtet
|
||||
comment7.target=void\ setGerichtet(boolean)
|
||||
comment7.text=\r\n\ Legt\ fest,\ ob\ der\ Graph\ gerichtet\ oder\ ungerichtet\ ist.\r\n\r\n\ @param\ \ isGerichtet\ neuer\ Wert\r\n
|
||||
comment8.params=
|
||||
comment8.target=boolean\ isGerichtet()
|
||||
comment8.text=\r\n\ Gibt\ zurueck,\ ob\ der\ Graph\ gerichtet\ oder\ ungerichtet\ ist.\r\n\r\n\ @return\ \ gerichtet?\ (true/false)\r\n
|
||||
comment9.params=k
|
||||
comment9.target=int\ getNummer(Knoten)
|
||||
comment9.text=\ Gibt\ die\ Nummer\ eines\ Knotens\ im\ Graphen\ zur\u00FCck\r\n\ @param\ \ k\ \ gesuchter\ Knoten\r\n\ @return\ Nummer\ des\ Knotens\ (mit\ 0\ beginnend)\r\n
|
||||
numComments=46
|
||||
800
graph/Graph.java
Normal file
800
graph/Graph.java
Normal file
|
|
@ -0,0 +1,800 @@
|
|||
package graph;
|
||||
import imp.*;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Dies ist das Herz vom "GraphTester" - der Graph selber, gepeichert als Adjazenzliste.
|
||||
* Die Klasse erlaubt durch geeignete Methoden:
|
||||
* - die Speicherung als Adjazenzmatrix,
|
||||
* - das Hinzufuegen und Loeschen von knoten und Kanten,
|
||||
* - das Markieren von Knoten und Kanten,
|
||||
* - eine Aussage darueber, ob Knoten oder Kanten enthalten sind und
|
||||
* - eine Ausgabe des Graphen in textueller Form sowie als csv-Datei.
|
||||
*
|
||||
*
|
||||
* @author Dirk Zechnall, Thomas Schaller
|
||||
* @version 31.01.2021 (v6.5)
|
||||
*/
|
||||
|
||||
public class Graph
|
||||
{
|
||||
|
||||
private ArrayList<Knoten> kList; // Liste aller Knoten
|
||||
private ArrayList<Kante> kaList; // Liste aller Kanten
|
||||
private ArrayList<ArrayList<Kante>> adList; //Adjazenzliste
|
||||
private boolean gerichtet;
|
||||
private boolean gewichtet;
|
||||
|
||||
/**
|
||||
* Der Konstruktor erstellt einen neuen Graphen (genauer eine neue Adjazenzliste)
|
||||
* @param isGerichtet gibt an, ob es sich um einen gerichteten Graphen handelt
|
||||
* @param isGewichtet gibt an, ob die Kanten gewichtet sind.
|
||||
*/
|
||||
public Graph (boolean isGerichtet, boolean isGewichtet) {
|
||||
loescheGraph();
|
||||
gerichtet = isGerichtet;
|
||||
gewichtet = isGewichtet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Der Konstruktor erstellt einen neuen ungerichteten, ungewichteten Graphen (genauer eine neue Adjazenzliste)
|
||||
*/
|
||||
public Graph() {
|
||||
loescheGraph();
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht alle Knoten und Kanten eines Graphen und stellt auf ungerichtet und ungewichtet zurück.
|
||||
*/
|
||||
public void loescheGraph() {
|
||||
gerichtet = false;
|
||||
gewichtet = false;
|
||||
kList = new ArrayList<Knoten>();
|
||||
kaList = new ArrayList<Kante>();
|
||||
adList = new ArrayList<ArrayList<Kante>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ein Graph wird aus einer csv-Datei erstellt, die entweder
|
||||
* eine Matrix oder eine Adjazenzliste enthält, die den Graph beschreibt.
|
||||
*
|
||||
* @param csvParser Eine CSV-Datei als Table-Objekt
|
||||
* @return gibt zurück, ob das Laden erfolgreich war
|
||||
*/
|
||||
public boolean ladeGraph(Table csvParser) {
|
||||
boolean geschafft = false;
|
||||
try {
|
||||
int knotenAnzahl = 0;
|
||||
boolean hasInfotext = false;
|
||||
boolean hasStatus = false;
|
||||
geschafft = true;
|
||||
int start;
|
||||
int posx = 0;
|
||||
|
||||
for(start = 0; start < csvParser.getRowCount(); start++) {
|
||||
TableRow row = csvParser.getRow(start);
|
||||
String m = row.getString(0);
|
||||
if(row.getString(0).equals("directed")) {
|
||||
setGerichtet(row.getInt(1) == 1);
|
||||
}
|
||||
if(row.getString(0).equals("weighted")) {
|
||||
setGewichtet(row.getInt(1) == 1);
|
||||
}
|
||||
if(row.getString(0).equals("matrix") || row.getString(0).equals("list")) {
|
||||
String n = row.getString(1);
|
||||
if(n.equals("infotext")) {
|
||||
hasInfotext = true;
|
||||
posx++;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Knoten erstellen
|
||||
for(int i=start+1; i < csvParser.getRowCount(); i++) {
|
||||
TableRow row = csvParser.getRow(i);
|
||||
if(row.getString(0).isEmpty() || row.getString(0).charAt(0) != '#') {
|
||||
Knoten k = new Knoten(row.getInt(posx), row.getInt(posx+1));
|
||||
if(hasInfotext) k.setInfotext(row.getString(0));
|
||||
|
||||
neuerKnoten(k);
|
||||
knotenAnzahl++;
|
||||
}
|
||||
}
|
||||
|
||||
// Kanten erstellen
|
||||
int k=0;
|
||||
if(csvParser.getString(start,0).equals("matrix")){
|
||||
|
||||
for(int i = start+1; i < csvParser.getRowCount(); i++) {
|
||||
TableRow row = csvParser.getRow(i);
|
||||
if(row.getString(0).isEmpty() || row.getString(0).charAt(0) != '#') { //Ueberpruefung auf Kommentare #
|
||||
for(int j = posx+2; j < row.getColumnCount(); j+=1) {
|
||||
if(!(row.getString(j).equals("-"))) {
|
||||
neueKante(getKnoten(k), getKnoten(j - 2 -posx), row.getDouble(j));
|
||||
}
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for(int i = start+1; i < csvParser.getRowCount(); i++) {
|
||||
|
||||
TableRow row = csvParser.getRow(i);
|
||||
if(row.getString(0).isEmpty() || row.getString(0).charAt(0) != '#') { // Ueberpruefung auf Kommentare #
|
||||
int z = row.getColumnCount();
|
||||
z++;
|
||||
|
||||
for(int j = posx+2; j < row.getColumnCount(); j+= 1) {
|
||||
if(isGewichtet()){
|
||||
neueKante(getKnoten(k), getKnoten(row.getInt(j)), row.getDouble(j + 1));
|
||||
j++;
|
||||
} else {
|
||||
neueKante(getKnoten(k), getKnoten(row.getInt(j)), 0);
|
||||
}
|
||||
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
geschafft=false;
|
||||
}
|
||||
return geschafft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legt fest, ob der Graph gewichtet oder ungewichtet ist.
|
||||
*
|
||||
* @param isGewichtet neuer Wert
|
||||
*/
|
||||
public void setGewichtet(boolean isGewichtet) {
|
||||
gewichtet = isGewichtet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt zurueck, ob der Graph gewichtet oder ungewichtet ist
|
||||
*
|
||||
* @return gewichtet? (true/false)
|
||||
*/
|
||||
public boolean isGewichtet() {
|
||||
return gewichtet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legt fest, ob der Graph gerichtet oder ungerichtet ist.
|
||||
*
|
||||
* @param isGerichtet neuer Wert
|
||||
*/
|
||||
public void setGerichtet(boolean isGerichtet) {
|
||||
gerichtet = isGerichtet;
|
||||
if(gerichtet) {
|
||||
for(Kante k: kaList) {
|
||||
adList.get(kList.indexOf(k.getZiel())).remove(k);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt zurueck, ob der Graph gerichtet oder ungerichtet ist.
|
||||
*
|
||||
* @return gerichtet? (true/false)
|
||||
*/
|
||||
public boolean isGerichtet() {
|
||||
return gerichtet;
|
||||
}
|
||||
|
||||
/** Gibt die Nummer eines Knotens im Graphen zurück
|
||||
* @param k gesuchter Knoten
|
||||
* @return Nummer des Knotens (mit 0 beginnend)
|
||||
*/
|
||||
public int getNummer(Knoten k) {
|
||||
return kList.indexOf(k);
|
||||
}
|
||||
|
||||
/** Gibt die Nummer einer Kante zurück
|
||||
* @param k gesuchte Kante
|
||||
* @return Nummer der Kante (mit 0 beginnend)
|
||||
*/
|
||||
public int getNummer(Kante k) {
|
||||
return kaList.indexOf(k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Methode getAdjazenzMatrix() gibt die Adjazenzmatrix zurueck.
|
||||
*
|
||||
* @return double[][] Die AdjazenzMatrix als zweidimensionales Array
|
||||
*/
|
||||
public double[][] getAdjazenzMatrix() {
|
||||
double[][] matrix = new double[getAnzahlKnoten()][getAnzahlKnoten()];
|
||||
for (int i=0; i<matrix.length; i++){
|
||||
for (int j=0; j<matrix[i].length; j++){
|
||||
matrix[i][j] = Double.NaN;
|
||||
}
|
||||
}
|
||||
// speichere Liste In Matrix
|
||||
for(Kante k : getAlleKanten()) {
|
||||
int startKnotenNummer = getNummer(k.getStart());
|
||||
int zielKnotenNummer = getNummer(k.getZiel());
|
||||
// Wenn keine Kanten existieren, gibt es auch kein Kantengewicht - daher wird hier das Kantengewicht auf NaN ueberprueft
|
||||
// man koennte hier auch mit Double-Variablen arbeiten und diese null setzen --> hat jedoch einen deutlich groeßeren Speicheraufwand!
|
||||
if(gewichtet) matrix[startKnotenNummer][zielKnotenNummer] = k.getGewicht();
|
||||
else matrix[startKnotenNummer][zielKnotenNummer] = 0;
|
||||
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine Liste aller Kanten des Graphen zurück.
|
||||
* @param filter optionaler Filter, der auf die Liste angewendet wird. Er muss einen boolean-Wert zurückgeben: z.B. @literal{k->k.isMarkiert() && k.isBesucht()}
|
||||
* @return Liste aller Kanten
|
||||
*/
|
||||
public List<Kante> getAlleKanten(Predicate<Kante>... filter) {
|
||||
List<Kante> kanten = new ArrayList<Kante>(kaList);
|
||||
if(filter.length>0) {
|
||||
kanten = kanten.stream() // convert list to stream
|
||||
.filter(filter[0])
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
return kanten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt die Markierung bei allen Knoten des Graphen.
|
||||
*/
|
||||
public void entferneMarkierungBeiAllenKnoten() {
|
||||
for (Knoten k : kList) {
|
||||
k.setMarkiert(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialisiert alle Knoten des Graphen.
|
||||
*/
|
||||
public void initialisiereAlleKnoten() {
|
||||
for (Knoten k : kList) {
|
||||
k.init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialisiert alle Kanten des Graphen.
|
||||
*/
|
||||
public void initialisiereAlleKanten() {
|
||||
for (Kante k: kaList) {
|
||||
k.init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ueberprueft, ob ein Knoten in der Knotenliste enthalten ist.
|
||||
* Sobald in der Knotenliste der Knoten k gefunden wird, wird true ausgegeben.
|
||||
*
|
||||
* @param k Der gesuchte Knoten
|
||||
* @return true= ist enthalten, false = ist nicht enthalten
|
||||
*/
|
||||
public boolean isKnotenEnthalten (Knoten k) {
|
||||
return kList.contains(k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Anzahl der Knoten im Graph zurueck
|
||||
*
|
||||
* @return Anzahl der Knoten
|
||||
*/
|
||||
public int getAnzahlKnoten() {
|
||||
return kList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine Liste aller Knoten des Graphen zurueck.
|
||||
* @param filter optionaler Filter, der auf die Liste angewendet wird. Er muss einen boolean-Wert zurückgeben: z.B. @literal{k->k.isMarkiert() && k.isBesucht()}
|
||||
* @return Die Knotenliste. Falls leer wird eine leere Liste zurueckgegeben
|
||||
*/
|
||||
public List<Knoten> getAlleKnoten(Predicate<Knoten>... filter) {
|
||||
List<Knoten> knoten = new ArrayList<Knoten>();
|
||||
knoten.addAll(kList);
|
||||
if(filter.length>0) {
|
||||
knoten = knoten.stream() // convert list to stream
|
||||
.filter(filter[0])
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
return knoten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Liste aller Nachbarknoten eines Knotens k zurueck, falls k in der Knotenliste vorhanden ist.
|
||||
*
|
||||
* @param k Der Knoten, zu dem die Adjazenzliste gesucht wird
|
||||
* @param filter optionaler Filter, der auf die Liste angewendet wird. Er muss einen boolean-Wert zurückgeben: z.B. @literal{k->k.isMarkiert() && k.isBesucht()}
|
||||
* @return Liste der Nachbarknoten
|
||||
*/
|
||||
public List<Knoten> getNachbarknoten (Knoten k, Predicate<Knoten>... filter) {
|
||||
if(kList.contains(k)) {
|
||||
List<Knoten> nachbarn = new ArrayList<Knoten>();
|
||||
for (Kante e : adList.get(kList.indexOf(k))) {
|
||||
nachbarn.add(e.getAnderesEnde(k));
|
||||
} // end of for
|
||||
if(filter.length>0) {
|
||||
nachbarn = nachbarn.stream() // convert list to stream
|
||||
.filter(filter[0])
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
return nachbarn;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine Liste der ausgehenden Kanten eines Knotens k zurueck, falls k in der Knotenliste vorhanden ist.
|
||||
* Bei ungerichteten Graphen wird nicht zwischen eingehenden und ausgehenden Kanten
|
||||
* unterschieden.
|
||||
*
|
||||
* @param k Der Knoten, zu dem die Kanten gesucht werden
|
||||
* @param filter optionaler Filter, der auf die Liste angewendet wird. Er muss einen boolean-Wert zurückgeben: z.B. @literal{k->k.isMarkiert() && k.isBesucht()}
|
||||
* @return Liste der ausgehenden Kanten.
|
||||
*/
|
||||
public List<Kante> getAusgehendeKanten (Knoten k, Predicate<Kante>... filter) {
|
||||
if(kList.contains(k)) {
|
||||
List<Kante> kanten = new ArrayList<Kante>();
|
||||
kanten.addAll(adList.get(kList.indexOf(k)));
|
||||
if(filter.length>0) {
|
||||
kanten = kanten.stream() // convert list to stream
|
||||
.filter(filter[0])
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
return kanten;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine Liste der ausgehenden Kanten eines Knotens k zurueck, falls k in der Knotenliste vorhanden ist.
|
||||
* Bei ungerichteten Graphen wird nicht zwischen eingehenden und ausgehenden Kanten
|
||||
* unterschieden.
|
||||
*
|
||||
* @param knotennr Nummer des Knoten, zu dem die Kanten gesucht werden
|
||||
* @param filter optionaler Filter, der auf die Liste angewendet wird. Er muss einen boolean-Wert zurückgeben: z.B. @literal{k->k.isMarkiert() && k.isBesucht()}
|
||||
* @return Liste der ausgehenden Kanten.
|
||||
*/
|
||||
public List<Kante> getAusgehendeKanten (int knotennr, Predicate<Kante>... filter) {
|
||||
if(knotennr < getAnzahlKnoten()) {
|
||||
List<Kante> kanten = new ArrayList<Kante>();
|
||||
kanten.addAll(adList.get(knotennr));
|
||||
if(filter.length>0) {
|
||||
kanten = kanten.stream() // convert list to stream
|
||||
.filter(filter[0])
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
return kanten;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine Liste der eingehenden Kanten eines Knotens k zurueck, falls k in der Knotenliste vorhanden ist.
|
||||
* Bei ungerichteten Graphen wird nicht zwischen eingehenden und ausgehenden Kanten
|
||||
* unterschieden.
|
||||
*
|
||||
* @param knotennr Die Nummer des Knotens, zu dem die Kanten gesucht werden
|
||||
* @param filter optionaler Filter, der auf die Liste angewendet wird. Er muss einen boolean-Wert zurückgeben: z.B. @literal{k->k.isMarkiert() && k.isBesucht()}
|
||||
* @return Liste der eingehenden Kanten.
|
||||
*/
|
||||
public List<Kante> getEingehendeKanten (int knotennr, Predicate<Kante>... filter) {
|
||||
if(knotennr >= getAnzahlKnoten()) {
|
||||
return null;
|
||||
}
|
||||
return getEingehendeKanten(this.getKnoten(knotennr),filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine Liste der eingehenden Kanten eines Knotens k zurueck, falls k in der Knotenliste vorhanden ist.
|
||||
* Bei ungerichteten Graphen wird nicht zwischen eingehenden und ausgehenden Kanten
|
||||
* unterschieden.
|
||||
*
|
||||
* @param k Knoten, zu dem die Kanten gesucht werden
|
||||
* @param filter optionaler Filter, der auf die Liste angewendet wird. Er muss einen boolean-Wert zurückgeben: z.B. @literal{k->k.isMarkiert() && k.isBesucht()}
|
||||
* @return Liste der eingehenden Kanten.
|
||||
*/
|
||||
|
||||
public List<Kante> getEingehendeKanten (Knoten k, Predicate<Kante>... filter) {
|
||||
if(!kList.contains(k)) {
|
||||
return null;
|
||||
}
|
||||
List<Kante> kanten = new ArrayList<Kante>();
|
||||
if(this.isGerichtet()) {
|
||||
for (Kante e: kaList) {
|
||||
if(e.getZiel()== k) {
|
||||
kanten.add(e);
|
||||
}
|
||||
} // end of for
|
||||
} else {
|
||||
kanten = getAusgehendeKanten(k);
|
||||
} // end of if-else
|
||||
|
||||
if(filter.length>0) {
|
||||
kanten = kanten.stream() // convert list to stream
|
||||
.filter(filter[0])
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
return kanten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert einen Knoten des Graphen
|
||||
* @param knotennr Nummer der Knoten (beginnend mit 0)
|
||||
* @return liefert den Knoten mit dieser Nummer
|
||||
*/
|
||||
public Knoten getKnoten(int knotennr) {
|
||||
if(knotennr < getAnzahlKnoten()) {
|
||||
return kList.get(knotennr);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fügt einen Knoten dem Graph hinzu.
|
||||
* @param k Der Knoten, der hinzugefuegt werden soll
|
||||
*/
|
||||
public void neuerKnoten (Knoten k) {
|
||||
if (!isKnotenEnthalten(k)){
|
||||
kList.add(k);
|
||||
adList.add(new ArrayList<Kante>());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt einen Knoten aus dem Graphen
|
||||
*
|
||||
* @param knotennr Nummer des Knotens, der geloescht werden soll
|
||||
*/
|
||||
public void entferneKnoten (int knotennr) {
|
||||
entferneKnoten(getKnoten(knotennr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt einen Knoten aus dem Graphen
|
||||
*
|
||||
* @param k Knoten, der geloescht werden soll
|
||||
* @return gibt zurück, ob der Knoten erfolgreich entfernt wurde.
|
||||
*/
|
||||
|
||||
public boolean entferneKnoten (Knoten k) {
|
||||
if (!kList.contains(k)) return false;
|
||||
|
||||
int index = kList.indexOf(k);
|
||||
for (List<Kante> a : adList) {
|
||||
int index2 = 0;
|
||||
while(index2 < a.size()){
|
||||
Kante ka = a.get(index2);
|
||||
if(ka.getStart()==k || ka.getZiel()==k){
|
||||
if(kaList.contains(ka)) kaList.remove(ka);
|
||||
a.remove(index2);
|
||||
} else {
|
||||
index2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
adList.remove(index);
|
||||
kList.remove(k);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ueberprueft, ob eine Kante im Graphen enthalten ist.
|
||||
*
|
||||
* @param e Die zu suchende Kante
|
||||
* @return Kante enthalten (true) oder nicht (false)
|
||||
*/
|
||||
public boolean isKanteEnthalten (Kante e) {
|
||||
return kaList.contains(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ueberprueft, ob eine Kante im Graphen enthalten ist.
|
||||
* In ungerichteten Graphen wird nicht zwischen Start- und Zielknoten unterschieden
|
||||
*
|
||||
* @param startNr Nummer des Startknotens
|
||||
* @param zielNr Nummer des Zielknotens
|
||||
* @return boolean Kante enthalten (true) oder nicht (false)
|
||||
*/
|
||||
public boolean isKanteEnthalten (int startNr, int zielNr) {
|
||||
return getKante(startNr, zielNr)!=null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ueberprueft, ob eine Kante im Graphen enthalten ist.
|
||||
* In ungerichteten Graphen wird nicht zwischen Start- und Zielknoten unterschieden
|
||||
*
|
||||
* @param start Startknoten
|
||||
* @param ziel Zielknoten
|
||||
* @return boolean Kante enthalten (true) oder nicht (false)
|
||||
*/
|
||||
|
||||
public boolean isKanteEnthalten (Knoten start, Knoten ziel) {
|
||||
return getKante(start, ziel)!=null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine gesuchte Kante aus dem Graphen zurueck.
|
||||
* In ungerichteten Graphen wird nicht zwischen Start- und Zielknoten unterschieden
|
||||
*
|
||||
* @param start Der StartKnoten
|
||||
* @param ziel Der StartKnoten
|
||||
* @return Die gesuchte Kante
|
||||
*/
|
||||
public Kante getKante (Knoten start, Knoten ziel) {
|
||||
|
||||
for(Kante k: adList.get(kList.indexOf(start))) {
|
||||
if(k.getStart()==start && k.getZiel() == ziel) {
|
||||
return k;
|
||||
}
|
||||
if(!gerichtet && k.getStart()==ziel && k.getZiel() == start) {
|
||||
return k;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine gesuchte Kante aus dem Graphen zurueck.
|
||||
* In ungerichteten Graphen wird nicht zwischen Start- und Zielknoten unterschieden
|
||||
*
|
||||
* @param startnr Der Nummer des StartKnoten
|
||||
* @param zielnr Die Nummer des Zielknoten
|
||||
* @return Die gesuchte Kante
|
||||
*/
|
||||
public Kante getKante (int startnr, int zielnr) {
|
||||
return getKante(getKnoten(startnr), getKnoten(zielnr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fuegt eine Kante dem Graphen hinzu.
|
||||
* Dabei wird ueberprueft, ob die Kante schon im Graphen enthalten ist.
|
||||
*
|
||||
* Ist der Graph ungerichtet, werden sowohl "Hin-" und "RueckKante" erstellt.
|
||||
*
|
||||
* @param e Die Kante, die hinzugefuegt werden soll
|
||||
*/
|
||||
public void neueKante(Kante e) {
|
||||
adList.get(kList.indexOf(e.getStart())).add(e);
|
||||
if(!gerichtet) adList.get(kList.indexOf(e.getZiel())).add(e);
|
||||
kaList.add(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fuegt eine Kante dem Graphen hinzu.
|
||||
* Dabei wird ueberprueft, ob die Kante schon im Graphen enthalten ist.
|
||||
*
|
||||
* Ist der Graph ungerichtet, werden sowohl "Hin-" und "RueckKante" erstellt.
|
||||
*
|
||||
* @param start Der StartKnoten der Kante, die hinzugefuegt werden soll
|
||||
* @param ziel Der ZielKnoten der Kante, die hinzugefuegt werden soll
|
||||
* @param gewicht Das Gewicht der Kante, die hinzugefuegt werden soll
|
||||
*/
|
||||
public void neueKante(Knoten start, Knoten ziel, double gewicht) {
|
||||
if(!kList.contains(start) || !kList.contains(ziel) || getKante(start,ziel) != null) return;
|
||||
neueKante(new Kante(start,ziel, gewicht));
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt eine Kante aus dem Graphen.
|
||||
* Ist der Graph ungerichtet, werden sowohl "Hin-" und "RueckKante" entfernt.
|
||||
*
|
||||
* @param e Die zu entfernende Kante
|
||||
*/
|
||||
public void entferneKante (Kante e) {
|
||||
entferneKante(e.getStart(), e.getZiel());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt eine Kante aus dem Graphen.
|
||||
* Dabei wird ueberprueft, ob die Kante ueberhaupt im Graphen enthalten ist.
|
||||
*
|
||||
* Ist der Graph ungerichtet, werden sowohl "Hin-" und "RueckKante" entfernt.
|
||||
*
|
||||
* @param start StartKnotens
|
||||
* @param ziel ZielKnotens
|
||||
*/
|
||||
public void entferneKante (Knoten start, Knoten ziel) {
|
||||
Kante e1 = getKante(start, ziel);
|
||||
Kante e2 = getKante(ziel, start);
|
||||
|
||||
for(List<Kante> a: adList) {
|
||||
a.remove(e1);
|
||||
if(!gerichtet) {
|
||||
a.remove(e2);
|
||||
}
|
||||
}
|
||||
kaList.remove(e1);
|
||||
if(!gerichtet) {
|
||||
kaList.remove(e2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt eine Kante aus dem Graphen.
|
||||
* Ist der Graph ungerichtet, werden sowohl "Hin-" und "RueckKante" entfernt.
|
||||
*
|
||||
* @param startnr Nummer des StartKnotens
|
||||
* @param zielnr Nummer des ZielKnotens
|
||||
*/
|
||||
public void entferneKante (int startnr, int zielnr) {
|
||||
entferneKante(getKnoten(startnr), getKnoten(zielnr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ueberprueft, ob die Adjazenzliste leer ist, d.h. keine Knoten im Graphen enthalten sind.
|
||||
*
|
||||
* @return true, wenn die Liste leer ist, sonst false
|
||||
*/
|
||||
public boolean isLeer() {
|
||||
return adList.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loescht den gesamten Graphen
|
||||
*/
|
||||
public void loescheAlles() {
|
||||
adList.clear();
|
||||
kList.clear();
|
||||
kaList.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Methode erstellt eine CSV-Ausgabe des Graphen entweder als Adjazenzliste oder als Adjazenzmatrix.
|
||||
*
|
||||
* @param asMatrix true, falls die CSV-Ausgabe eine AdjazenzMatrix sein soll, sonst false
|
||||
* @return CSV-Ausgabe
|
||||
*/
|
||||
|
||||
public String toCSVString(boolean asMatrix) {
|
||||
String s="";
|
||||
//if(adList.isLeer()) return s;
|
||||
s += "# gewichtet 1, ungewichtet 0\n";
|
||||
s += "weighted,"+(isGewichtet() ? "1" : "0")+"\n";
|
||||
s += "# gerichtet 1, ungerichtet 0\n";
|
||||
s += "directed,"+(isGerichtet() ? "1" : "0")+"\n";
|
||||
|
||||
// Kontrollieren, ob irgendwo ein Infotext vorhanden ist.
|
||||
boolean hasInfotext = false;
|
||||
for(Knoten k: kList) {
|
||||
if(!k.getInfotext().equals("")) hasInfotext = true;
|
||||
}
|
||||
|
||||
if(asMatrix){
|
||||
s += "# Der Graph liegt hier in Form einer Adjazenzmatrix vor. \n";
|
||||
s += "# Jede Zeile steht fuer einen Knoten, durch Kommas getrennt stehen die Kantengewicht zu jedem anderen Knoten.\n";
|
||||
|
||||
s += "matrix";
|
||||
if(hasInfotext) s+=",infotext";
|
||||
double[][] matrix = getAdjazenzMatrix();
|
||||
// hier muss ueberprueft werden, ob matrixinhalt ist NaN --> '-' speichern
|
||||
for (int i=0; i<matrix.length; i++){
|
||||
s+="\n";
|
||||
Knoten k = kList.get(i);
|
||||
if(hasInfotext) s+=k.getInfotext()+",";
|
||||
s+=(k.getX())+","+k.getY()+",";
|
||||
for (int j=0; j<matrix[i].length; j++){
|
||||
if(Double.isNaN(matrix[i][j]))s+="-";
|
||||
else s+=matrix[i][j];
|
||||
if (j!=matrix.length-1) s+=",";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
s += "# Der Graph liegt hier in Form einer Adjazenzliste vor.\n";
|
||||
s += "# Jede Zeile steht fuer einen Knoten, durch Komma getrennt steht der adjazente Knoten mit dem zugehoerigen Kantengewicht.\n";
|
||||
s += "list";
|
||||
if(hasInfotext) s+=",infotext";
|
||||
|
||||
for(int knr = 0; knr < kList.size(); knr++) {
|
||||
s+="\n";
|
||||
Knoten k = kList.get(knr);
|
||||
List<Kante> a = adList.get(knr);
|
||||
if(hasInfotext) s+=k.getInfotext()+",";
|
||||
s+=(k.getX())+","+(k.getY());
|
||||
if (a.size()>0) s+=",";
|
||||
for (Kante ka : a) {
|
||||
s+=""+(getNummer(ka.getAnderesEnde(k)));
|
||||
if (isGewichtet()) s+=","+ka.getGewicht();
|
||||
if (a.get(a.size()-1)!=ka) s+=",";
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Textuelle Repraesentation des Graphen.
|
||||
*
|
||||
* @return Der Graph als Stringrepraesentation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
String s="";
|
||||
s+="Adjazenzliste:\n";
|
||||
if(adList.isEmpty()) return "Liste ist leer!\n";
|
||||
for(int i=0; i< kList.size(); i++) {
|
||||
s+="K"+i+kList.get(i).toString()+": ";
|
||||
List<Kante> a =adList.get(i);
|
||||
for (Kante k : a) {
|
||||
s+=k.toString()+"K"+(kList.indexOf(k.getAnderesEnde(kList.get(i))))+" | ";
|
||||
}
|
||||
s=s.substring(0,s.length()-3)+"\n";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Konsolenausgabe der textuellen Repraesentation des Graphen.
|
||||
*/
|
||||
public void ausgabe() {
|
||||
System.out.println(toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Info über einen Knoten zurückgeben
|
||||
* @param k Knoten, des Info ermittelt werden soll
|
||||
* @param zeigeWert Soll der Wert des Knoten in der Info enthalten sein
|
||||
* @return Infotext oder Nummer des Knoten und ggf. sein Wert
|
||||
*/
|
||||
public String getKnoteninfo(Knoten k, boolean zeigeWert) {
|
||||
String info = "";
|
||||
if (!k.getInfotext().equals("")) {
|
||||
info += k.getInfotext();
|
||||
} else {
|
||||
info += "Knoten Nr. "+getNummer(k);
|
||||
}
|
||||
if( zeigeWert) {
|
||||
info += " (Wert "+k.getDoubleWert()+")";
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
/** Speichert den Zustand des Graphen als String-List
|
||||
* @return List mit Zustand
|
||||
*/
|
||||
public List<String> getStatus() {
|
||||
List<String> status = new ArrayList<String>();
|
||||
for(Knoten k : getAlleKnoten()) {
|
||||
status.add(k.getStatus());
|
||||
}
|
||||
for(Kante k : getAlleKanten()) {
|
||||
status.add(k.getStatus());
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Stellt den Zustand des Graphen aus String-List wieder her
|
||||
* @param status List mit Zustand
|
||||
*/
|
||||
public void setStatus(List<String> status) {
|
||||
int i=0;
|
||||
for(Knoten k : getAlleKnoten()) {
|
||||
k.setStatus(status.get(i++));
|
||||
}
|
||||
for(Kante k : getAlleKanten()) {
|
||||
k.setStatus(status.get(i++));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
16
graph/Graph.uml
Normal file
16
graph/Graph.uml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
[Diagram]
|
||||
comments=0
|
||||
OffsetX=0
|
||||
OffsetY=0
|
||||
Visibility=0
|
||||
ShowParameter=4
|
||||
SortOrder=0
|
||||
ShowIcons=0
|
||||
ShowConnections=0
|
||||
Fontname=Segoe UI
|
||||
Fontsize=10
|
||||
ShowObjectDiagram=0
|
||||
|
||||
[Interactive]
|
||||
I0=
|
||||
|
||||
10
graph/GraphElement.ctxt
Normal file
10
graph/GraphElement.ctxt
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#BlueJ class context
|
||||
comment0.target=GraphElement
|
||||
comment0.text=\r\n\ Die\ Klasse\ GraphElement\ ist\ eine\ Oberklasse\ von\ Knoten\ und\ Kanten.\r\n\ Sie\ ist\ nur\ f\u00FCr\ die\ interne\ Verarbeitung\ wichtig.\r\n\r\n\ @author\ Thomas\ Schaller\r\n\ @version\ v1.1\r\n
|
||||
comment1.params=e
|
||||
comment1.target=int\ compareTo(GraphElement)
|
||||
comment2.params=
|
||||
comment2.target=java.lang.String\ getStatus()
|
||||
comment3.params=status
|
||||
comment3.target=void\ setStatus(java.lang.String)
|
||||
numComments=4
|
||||
16
graph/GraphElement.java
Normal file
16
graph/GraphElement.java
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package graph;
|
||||
|
||||
|
||||
/**
|
||||
* Die Klasse GraphElement ist eine Oberklasse von Knoten und Kanten.
|
||||
* Sie ist nur für die interne Verarbeitung wichtig.
|
||||
*
|
||||
* @author Thomas Schaller
|
||||
* @version v1.1
|
||||
*/
|
||||
public abstract class GraphElement implements Comparable<GraphElement>
|
||||
{
|
||||
public abstract int compareTo(GraphElement e);
|
||||
public abstract String getStatus();
|
||||
public abstract void setStatus(String status);
|
||||
}
|
||||
12
graph/GraphOptions.ctxt
Normal file
12
graph/GraphOptions.ctxt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#BlueJ class context
|
||||
comment0.target=GraphOptions
|
||||
comment0.text=\r\n\ Die\ Klasse\ GraphOptions\ speichert,\ wie\ ein\ Graph\ in\ einem\ Fenster\ vom\ \r\n\ GraphPlotter\ angezeigt\ wird.\r\n\r\n\ @author\ Thomas\ Schaller\r\n\ @version\ v6.7\ (9.12.2020)\r\n
|
||||
comment1.params=
|
||||
comment1.target=GraphOptions()
|
||||
comment2.params=csvParser
|
||||
comment2.target=void\ ladeGraph(imp.Table)
|
||||
comment3.params=
|
||||
comment3.target=java.lang.String\ getText()
|
||||
comment4.params=
|
||||
comment4.target=GraphOptions\ copy()
|
||||
numComments=5
|
||||
167
graph/GraphOptions.java
Normal file
167
graph/GraphOptions.java
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
package graph;
|
||||
import imp.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Die Klasse GraphOptions speichert, wie ein Graph in einem Fenster vom
|
||||
* GraphPlotter angezeigt wird.
|
||||
*
|
||||
* @author Thomas Schaller
|
||||
* @version v6.7 (9.12.2020)
|
||||
*/
|
||||
public class GraphOptions
|
||||
{
|
||||
// Bild
|
||||
public String bildDatei = "";
|
||||
public boolean bildAnzeigen = false;
|
||||
|
||||
// Anzeigeeinstellungen
|
||||
public int vertexSize = 30;
|
||||
public boolean showEdgeWeights = true;
|
||||
public boolean showVertexValue = true;
|
||||
public boolean showVertexText = false;
|
||||
public boolean showVertexInfo = false;
|
||||
|
||||
// Speicheroption
|
||||
public boolean saveAsMatrix = false;
|
||||
|
||||
// Farben der Anzeige
|
||||
public String[] stdFarbenKnoten = {"D0D0D0", "ACFFAB", "ACFFED", "ACC5ED", "ACC582", "E5C582", "E5C5C2", "D19FFD", "FF9F8E","FF6158", "FF61D4", "FFDE6E", "770000", "007700", "000077", "777700", "77a0e0", "9912E4", "783410", "12a94e"};
|
||||
public String[] stdFarbenKanten = {"606060", "5080FF", "D0D0D0"};
|
||||
public String[] farbenKnoten = stdFarbenKnoten;
|
||||
public String[] farbenKanten = stdFarbenKanten;
|
||||
|
||||
// Auswahl der anzuzeigenden Knoten
|
||||
public int fokusArt = 0; // 0 = Knoten, 1 = Kanten
|
||||
public GraphElement parent = null;
|
||||
public int auswahl = 0; // 0 = alle, 1 = Nachbarn, 2 = Single
|
||||
|
||||
public GraphOptions() {
|
||||
}
|
||||
|
||||
public void ladeGraph(Table csvParser) {
|
||||
farbenKnoten = stdFarbenKnoten;
|
||||
farbenKanten = stdFarbenKanten;
|
||||
vertexSize = 30;
|
||||
|
||||
showEdgeWeights = true;
|
||||
showVertexText = true;
|
||||
showVertexValue = false;
|
||||
showVertexInfo = false;
|
||||
bildDatei = "";
|
||||
|
||||
fokusArt = 0; // 0 = Knoten, 1 = Kanten
|
||||
parent = null;
|
||||
auswahl = 0;
|
||||
|
||||
for(int i = 0; i < csvParser.getRowCount(); i++) {
|
||||
TableRow row = csvParser.getRow(i);
|
||||
|
||||
if(row.getString(0).equals("showWeights")) {
|
||||
showEdgeWeights = (row.getInt(1) == 1);
|
||||
}
|
||||
if(row.getString(0).equals("showInfoText")) {
|
||||
showVertexInfo = (row.getInt(1) == 1);
|
||||
}
|
||||
|
||||
if(row.getString(0).equals("vertexSize")) {
|
||||
vertexSize = row.getInt(1);
|
||||
}
|
||||
if(row.getString(0).equals("vertexStyle")) {
|
||||
showVertexText = (row.getInt(1) == 1);
|
||||
showVertexValue = (row.getInt(1) == 2);
|
||||
}
|
||||
if(row.getString(0).equals("image")) {
|
||||
if(row.getString(1).charAt(0) == '0'){
|
||||
bildDatei = "";
|
||||
bildAnzeigen = false;
|
||||
} else {
|
||||
bildDatei = row.getString(1);
|
||||
bildAnzeigen = true;
|
||||
}
|
||||
}
|
||||
if(row.getString(0).equals("vertexColor")) {
|
||||
farbenKnoten = Arrays.copyOfRange(csvParser.getStringRow(i), 1, row.getColumnCount());
|
||||
}
|
||||
if(row.getString(0).equals("edgeColor")) {
|
||||
farbenKanten = Arrays.copyOfRange(csvParser.getStringRow(i), 1, row.getColumnCount());
|
||||
}
|
||||
if(row.getString(0).equals("matrix") || row.getString(0).equals("list")) {
|
||||
if(row.getString(0).equals("matrix"))
|
||||
saveAsMatrix = true;
|
||||
else
|
||||
saveAsMatrix = false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
String gesamtText = "# Anzeigeoptionen:";
|
||||
gesamtText += "# Gewichte anzeigen 1, Gewichte nicht anzeigen 0\n";
|
||||
if(showEdgeWeights)
|
||||
gesamtText += "showWeights,1\n";
|
||||
else
|
||||
gesamtText += "showWeights,0\n";
|
||||
if(vertexSize != 30) {
|
||||
gesamtText += "# Größe der Knoten\n";
|
||||
gesamtText += "vertexSize,"+vertexSize+"\n";
|
||||
}
|
||||
gesamtText += "# Knoteninfo anzeigen 1,Knoteninfo nicht anzeigen 0\n";
|
||||
if(showVertexInfo)
|
||||
gesamtText += "showInfoText,1\n";
|
||||
else
|
||||
gesamtText += "showInfoText,0\n";
|
||||
|
||||
gesamtText += "# Knoten leer 0, Knotenname anzeigen 1, Wert des Knoten anzeigen 2\n";
|
||||
if(!showVertexText && !showVertexValue) gesamtText += "vertexStyle,0\n";
|
||||
else {
|
||||
if(showVertexText) gesamtText += "vertexStyle,1\n";
|
||||
else
|
||||
gesamtText += "vertexStyle,2\n";
|
||||
}
|
||||
if(farbenKanten!=stdFarbenKanten) {
|
||||
gesamtText += "# Kantenfarben: RGB-Hexcode (z.B. FF0000) oder invisible\n";
|
||||
gesamtText += "# Reihenfolge: normale Kanten, markierte Kanten, gelöschte Kanten\n";
|
||||
gesamtText += "edgeColor";
|
||||
for(String f : farbenKanten) gesamtText+=","+f;
|
||||
gesamtText += "\n";
|
||||
}
|
||||
if(farbenKnoten!=stdFarbenKnoten) {
|
||||
gesamtText += "# Knotenfarben: RGB-Hexcode (z.B. FF0000) oder invisible\n";
|
||||
gesamtText += "# Reihenfolge: nichts, markiert, besucht, besucht und markiert\n";
|
||||
gesamtText += "# mind. 12 Farben müssen angegeben werden.";
|
||||
gesamtText += "vertexColor";
|
||||
for(String f : farbenKnoten) gesamtText+=","+f;
|
||||
gesamtText += "\n";
|
||||
}
|
||||
gesamtText += "# Bild im Hintergrund (bitte im \"images\"-Ordner ablegen) --> Dateiname angeben. Fall kein Bild bitte 0 schreiben!\n";
|
||||
if(bildDatei.equals(""))
|
||||
gesamtText += "image,0\n";
|
||||
else
|
||||
gesamtText += "image,"+bildDatei + "\n";
|
||||
return gesamtText;
|
||||
}
|
||||
|
||||
public GraphOptions copy() {
|
||||
GraphOptions kopie = new GraphOptions();
|
||||
kopie.bildDatei= bildDatei;
|
||||
kopie.bildAnzeigen = bildAnzeigen;
|
||||
kopie.vertexSize = vertexSize;
|
||||
kopie.showEdgeWeights = showEdgeWeights;
|
||||
kopie.showVertexValue = showVertexValue;
|
||||
kopie.showVertexText = showVertexText;
|
||||
kopie.showVertexInfo = showVertexInfo;
|
||||
kopie.saveAsMatrix = saveAsMatrix;
|
||||
kopie.stdFarbenKnoten = stdFarbenKnoten.clone();
|
||||
kopie.stdFarbenKanten = stdFarbenKanten.clone();
|
||||
kopie.farbenKnoten = farbenKnoten.clone();
|
||||
kopie.farbenKanten = farbenKanten.clone();
|
||||
kopie.fokusArt = fokusArt;
|
||||
kopie.auswahl = auswahl;
|
||||
kopie.parent = parent;
|
||||
return kopie;
|
||||
}
|
||||
|
||||
}
|
||||
57
graph/GraphPlotter.ctxt
Normal file
57
graph/GraphPlotter.ctxt
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#BlueJ class context
|
||||
comment0.target=GraphPlotter
|
||||
comment0.text=\r\n\ Der\ GraphPlotter\ ist\ das\ Herzstueck\ der\ Visualisierung\ und\ dient\ als\ Schnittstelle\ zur\ GUI.\r\n\ \r\n\ @author\ Thomas\ Schaller\r\n\ @version\ 09.12.2020\ (v6.7)\r\n
|
||||
comment1.params=
|
||||
comment1.target=GraphPlotter()
|
||||
comment1.text=\r\n\ Der\ Konstruktor\ legt\ sowohl\ Einstellungen\ des\ mxGraphen\ (Drag&Drop,\ Editable,\ ...)\ als\ auch\ des\ Graphen\ (gewichtet,\ gerichtet,\ ...)\ fest.\r\n\r\n\ @param\ \ boolean\ isDirected\ \ Gibt\ an,\ ob\ der\ Graph\ gerichtet\ oder\ ungerichtet\ ist\r\n\ @param\ \ boolean\ isWeighted\ \ Gibt\ an,\ ob\ der\ Graph\ gewichtet\ oder\ ungewichtet\ ist\r\n\ @param\ \ String\ hintergrundBild\ \ \ Gibt\ den\ Namen\ eines\ Hintergrundbildes\ an\r\n
|
||||
comment10.params=x\ y
|
||||
comment10.target=Knoten\ getKnotenAt(int,\ int)
|
||||
comment11.params=x\ y
|
||||
comment11.target=Kante\ getKanteAt(int,\ int)
|
||||
comment12.params=p\ startx\ starty\ endx\ endy
|
||||
comment12.target=void\ drawArrow(imp.Picture,\ int,\ int,\ int,\ int)
|
||||
comment13.params=color
|
||||
comment13.target=java.lang.String\ darker(java.lang.String)
|
||||
comment14.params=color
|
||||
comment14.target=java.lang.String\ brighter(java.lang.String)
|
||||
comment15.params=d
|
||||
comment15.target=java.lang.String\ format(double)
|
||||
comment16.params=
|
||||
comment16.target=imp.Picture\ updateImage()
|
||||
comment17.params=
|
||||
comment17.target=GraphOptions\ getGraphOptions()
|
||||
comment18.params=
|
||||
comment18.target=Graph\ getGraph()
|
||||
comment18.text=\r\n\ Gibt\ den\ Graphen\ zurueck.\r\n\ \r\n\ @return\ \ Graph\r\n
|
||||
comment19.params=
|
||||
comment19.target=Knoten\ getSelectedKnoten()
|
||||
comment19.text=\r\n\ Gibt\ das\ selektierte\ Knotenobjekt\ zurueck.\r\n\ \r\n\ @return\ \ Object\r\n
|
||||
comment2.params=
|
||||
comment2.target=void\ setEditable()
|
||||
comment20.params=
|
||||
comment20.target=java.util.List\ getSelectedKnotenListe()
|
||||
comment20.text=\r\n\ Gibt\ die\ selektierte\ KnotenobjektListe\ (als\ Array)\ zurueck.\r\n\ \r\n\ @return\ \ Object[]\r\n
|
||||
comment21.params=
|
||||
comment21.target=Kante\ getSelectedKante()
|
||||
comment21.text=\r\n\ Gibt\ das\ selektierte\ Kantenobjekt\ zurueck.\r\n\ \r\n\ @return\ \ Object\r\n
|
||||
comment22.params=
|
||||
comment22.target=java.lang.String\ toString()
|
||||
comment22.text=\r\n\ Ueberschreibt\ die\ Methode\ toString.\ Eine\ String-Repraesentation\ des\ GraphPlotters\ wird\ ausgegeben.\r\n\r\n\ @return\ \ String\ \ Die\ String-Repraesentation\ des\ GraphPlotters\r\n
|
||||
comment23.params=
|
||||
comment23.target=void\ ausgabe()
|
||||
comment23.text=\r\n\ Gibt\ die\ String-Repraesentation\ des\ GraphPlotters\ auf\ der\ Konsole\ aus.\r\n
|
||||
comment3.params=graph\ options
|
||||
comment3.target=void\ setGraph(Graph,\ GraphOptions)
|
||||
comment4.params=k
|
||||
comment4.target=void\ setRestrictTo(GraphElement)
|
||||
comment5.params=
|
||||
comment5.target=GraphElement\ getRestrictTo()
|
||||
comment6.params=mouseEvent
|
||||
comment6.target=void\ mouseClicked(javafx.scene.input.MouseEvent)
|
||||
comment7.params=mouseEvent
|
||||
comment7.target=void\ mouseDown(javafx.scene.input.MouseEvent)
|
||||
comment8.params=mouseEvent
|
||||
comment8.target=void\ mouseDragged(javafx.scene.input.MouseEvent)
|
||||
comment9.params=mouseEvent
|
||||
comment9.target=void\ mouseUp(javafx.scene.input.MouseEvent)
|
||||
numComments=24
|
||||
601
graph/GraphPlotter.java
Normal file
601
graph/GraphPlotter.java
Normal file
|
|
@ -0,0 +1,601 @@
|
|||
package graph;
|
||||
|
||||
import imp.*;
|
||||
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import java.nio.file.*;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
/**
|
||||
* Der GraphPlotter ist das Herzstueck der Visualisierung und dient als Schnittstelle zur GUI.
|
||||
*
|
||||
* @author Thomas Schaller
|
||||
* @version 09.12.2020 (v6.7)
|
||||
*/
|
||||
public class GraphPlotter extends PictureViewer {
|
||||
// Anfang Attribute
|
||||
private Graph graph;
|
||||
private GraphOptions options;
|
||||
|
||||
private boolean multiselect = false;
|
||||
private boolean editable = false;
|
||||
private ArrayList<GraphElement> selected=new ArrayList<GraphElement>();
|
||||
private Knoten dragKnoten = null;
|
||||
private int dragMode = 0;
|
||||
|
||||
// Tooltip
|
||||
private double mouseX, mouseY;
|
||||
private Tooltip t;
|
||||
|
||||
private GraphElement restrictTo = null;
|
||||
private Point2D offset = new Point2D(0,0);
|
||||
|
||||
// private JTextArea jTAMeldungen = new JTextArea("");
|
||||
// private JScrollPane jTAMeldungenScrollPane = new JScrollPane(jTAMeldungen);
|
||||
|
||||
// Ende Attribute
|
||||
|
||||
/**
|
||||
* Der Konstruktor legt sowohl Einstellungen des mxGraphen (Drag&Drop, Editable, ...) als auch des Graphen (gewichtet, gerichtet, ...) fest.
|
||||
*
|
||||
* @param boolean isDirected Gibt an, ob der Graph gerichtet oder ungerichtet ist
|
||||
* @param boolean isWeighted Gibt an, ob der Graph gewichtet oder ungewichtet ist
|
||||
* @param String hintergrundBild Gibt den Namen eines Hintergrundbildes an
|
||||
*/
|
||||
public GraphPlotter() {
|
||||
options = new GraphOptions();
|
||||
graph = new Graph();
|
||||
|
||||
this.setStyle("-fx-background:#FFFFE8");
|
||||
|
||||
// add(jTAMeldungenScrollPane, BorderLayout.SOUTH);
|
||||
setOnMouseClicked(mouseEvent -> mouseClicked(mouseEvent));
|
||||
// setOnMouseMoved(mouseEvent -> { mouseX = mouseEvent.getSceneX(); mouseY = mouseEvent.getSceneY(); t.hide();});
|
||||
this.widthProperty().addListener((value, oldWidth, newWidth) -> updateImage());
|
||||
this.heightProperty().addListener((value, oldWidth, newWidth) -> updateImage());
|
||||
|
||||
// t = new Tooltip();
|
||||
// Tooltip.install(this, t);
|
||||
// t.setPrefWidth(80);
|
||||
// t.setWrapText(true);
|
||||
// t.setHideOnEscape(true);
|
||||
// t.setStyle("-fx-background: rgba(30,30,30); -fx-text-fill: black; -fx-background-color: rgba(230,230,90,0.8);"+
|
||||
// "-fx-background-radius: 6px; -fx-background-insets: 0; -fx-padding: 0.667em 0.75em 0.667em 0.75em; "+
|
||||
// " -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.5) , 10, 0.0 , 0 , 3 ); -fx-font-size: 0.85em;");
|
||||
|
||||
// t.setShowDelay(Duration.seconds(1));
|
||||
// t.setOnShowing(ev -> {// called just prior to being shown
|
||||
// Point2D local = this.getContent().sceneToLocal(mouseX, mouseY);
|
||||
// Knoten k = getKnotenAt((int) local.getX(), (int) local.getY());
|
||||
// if(k == null) {
|
||||
// t.hide();
|
||||
// } else {
|
||||
// t.setText("Knoten Nr. "+graph.getNummer(k)+"\nWert: "+k.getDoubleWert());
|
||||
// }
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
public void setEditable() {
|
||||
editable = true;
|
||||
//setOnMousePressed(mouseEvent -> mouseDown(mouseEvent)); // wird durch MousePressed in EditTab realisiert und dann hier aufgerufen
|
||||
setOnMouseReleased(mouseEvent -> mouseUp(mouseEvent));
|
||||
setOnDragDetected(mouseEvent -> startFullDrag());
|
||||
setOnMouseDragOver(mouseEvent-> mouseDragged(mouseEvent));
|
||||
setOnMouseClicked(null);
|
||||
}
|
||||
|
||||
public void setGraph(Graph graph, GraphOptions options) {
|
||||
this.graph = graph;
|
||||
this.options = options;
|
||||
updateImage();
|
||||
}
|
||||
|
||||
public void setRestrictTo(GraphElement k) {
|
||||
if(restrictTo != k) {
|
||||
restrictTo = k;
|
||||
selected.clear();
|
||||
if (k!= null) selected.add(k);
|
||||
updateImage();
|
||||
}
|
||||
}
|
||||
|
||||
public GraphElement getRestrictTo() {
|
||||
return restrictTo;
|
||||
}
|
||||
|
||||
public void mouseClicked(MouseEvent mouseEvent) {
|
||||
|
||||
Point2D local = this.getContent().sceneToLocal(mouseEvent.getSceneX(), mouseEvent.getSceneY());
|
||||
GraphElement k = getKnotenAt((int) local.getX(), (int) local.getY());
|
||||
if(k!=null && mouseEvent.isShiftDown() && restrictTo != null && restrictTo instanceof Knoten) { // mit Shift-Knotenklick Kante auswählen, damit unsichtbare Kanten gewählt werden können (für TSP)
|
||||
k = graph.getKante((Knoten) restrictTo, (Knoten) k);
|
||||
}
|
||||
if(k!=null && mouseEvent.isShiftDown() && selected.size() == 1 && selected.get(0) instanceof Knoten) { // mit Shift-Knotenklick Kante auswählen, damit unsichtbare Kanten gewählt werden können (für TSP)
|
||||
k = graph.getKante((Knoten) (selected.get(0)), (Knoten) k);
|
||||
}
|
||||
if(k==null) k = getKanteAt((int) local.getX(), (int) local.getY());
|
||||
if(!multiselect) {
|
||||
selected.clear();
|
||||
}
|
||||
if(k != null) {
|
||||
if(selected.contains(k)) selected.remove(k);
|
||||
else selected.add(k);
|
||||
}
|
||||
updateImage();
|
||||
}
|
||||
|
||||
public void mouseDown(MouseEvent mouseEvent) {
|
||||
|
||||
if(mouseEvent.isPrimaryButtonDown()) {
|
||||
Point2D local = this.getContent().sceneToLocal(mouseEvent.getSceneX(), mouseEvent.getSceneY());
|
||||
dragKnoten = getKnotenAt((int) local.getX(), (int) local.getY());
|
||||
dragMode = 3; // Linksclick aber nicht auf Knoten
|
||||
if(dragKnoten != null) {
|
||||
mouseEvent.setDragDetect(true);
|
||||
double distance = Math.sqrt(Math.pow(local.getX()-dragKnoten.getX(),2)+Math.pow(local.getY()-dragKnoten.getY(),2));
|
||||
if(distance < options.vertexSize/4)
|
||||
dragMode = 1; // Knoten verschieben
|
||||
else
|
||||
dragMode = 2; // Kante ziehen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseDragged(MouseEvent mouseEvent) {
|
||||
|
||||
if(dragKnoten != null) {
|
||||
Point2D local = this.getContent().sceneToLocal(mouseEvent.getSceneX(), mouseEvent.getSceneY());
|
||||
if(dragMode == 1) {
|
||||
dragKnoten.setX((int) (local.getX()));
|
||||
dragKnoten.setY((int) (local.getY()));
|
||||
}
|
||||
updateImage();
|
||||
if(dragMode == 2) {
|
||||
Picture p = getImage();
|
||||
p.stroke(0);
|
||||
p.strokeWeight(3);
|
||||
//p.line(dragKnoten.getX(), dragKnoten.getY(), (int) local.getX(), (int) local.getY());
|
||||
drawArrow(p,dragKnoten.getX(), dragKnoten.getY(), (int) local.getX(), (int) local.getY());
|
||||
setImage(p,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseUp(MouseEvent mouseEvent) {
|
||||
|
||||
Point2D local = this.getContent().sceneToLocal(mouseEvent.getSceneX(), mouseEvent.getSceneY());
|
||||
Knoten k = getKnotenAt((int) local.getX(), (int) local.getY());
|
||||
if(dragMode == 3 && k==null && getKanteAt((int) local.getX(), (int) local.getY())==null) { // neuer Knoten
|
||||
graph.neuerKnoten(new Knoten((int)local.getX(), (int) local.getY())) ;
|
||||
} else {
|
||||
if(dragMode == 2 && k != null && k != dragKnoten) {
|
||||
graph.neueKante(dragKnoten, k, 0.0);
|
||||
}
|
||||
}
|
||||
dragKnoten = null;
|
||||
dragMode = 0;
|
||||
mouseEvent.setDragDetect(false);
|
||||
updateImage();
|
||||
|
||||
}
|
||||
|
||||
private Knoten getKnotenAt(int x, int y) {
|
||||
List<Knoten> knoten = graph.getAlleKnoten();
|
||||
if(restrictTo != null) {
|
||||
knoten.clear();
|
||||
if(restrictTo instanceof Knoten) {
|
||||
knoten = graph.getNachbarknoten((Knoten) restrictTo);
|
||||
knoten.add((Knoten) restrictTo);
|
||||
}
|
||||
if(restrictTo instanceof Kante) {
|
||||
knoten.add(((Kante) restrictTo).getStart());
|
||||
knoten.add(((Kante) restrictTo).getZiel());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(Knoten k : knoten) {
|
||||
if(Math.sqrt(Math.pow(k.getX()-x,2)+Math.pow(k.getY()-y,2)) < options.vertexSize/2+1) {
|
||||
return k;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Kante getKanteAt(int x, int y) {
|
||||
List<Kante> kanten = graph.getAlleKanten();
|
||||
if(restrictTo != null) {
|
||||
kanten.clear();
|
||||
if(restrictTo instanceof Knoten) {
|
||||
kanten = graph.getAusgehendeKanten((Knoten) restrictTo);
|
||||
}
|
||||
if(restrictTo instanceof Kante) {
|
||||
kanten.add(((Kante) restrictTo));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (Kante k: kanten) {
|
||||
if (x>=Math.min(k.getStart().getX(), k.getZiel().getX())-2 &&
|
||||
x<=Math.max(k.getStart().getX(), k.getZiel().getX())+2 &&
|
||||
y>=Math.min(k.getStart().getY(), k.getZiel().getY())-2 &&
|
||||
y<=Math.max(k.getStart().getY(), k.getZiel().getY())+2) {
|
||||
double startX = k.getStart().getX();
|
||||
double startY = k.getStart().getY();
|
||||
double endX = k.getZiel().getX();
|
||||
double endY = k.getZiel().getY();
|
||||
double dy = (endY-startY);
|
||||
double dx = (endX-startX);
|
||||
double l = Math.sqrt(dx*dx+dy*dy);
|
||||
dy = dy /l; dx = dx / l;
|
||||
startX += dx * (options.vertexSize/2+1);
|
||||
startY += dy * (options.vertexSize/2+1);
|
||||
endX -= dx * (options.vertexSize/2+1);
|
||||
endY -= dy * (options.vertexSize/2+1);
|
||||
double dx2 = dy*5;
|
||||
double dy2 = -dx*5;
|
||||
if (graph.isGerichtet() && graph.getKante(k.getZiel(), k.getStart())!=null){
|
||||
startX += dx2;
|
||||
startY += dy2;
|
||||
endX += dx2;
|
||||
endY += dy2;
|
||||
}
|
||||
double nx = dy;
|
||||
double ny = -dx;
|
||||
double abx = x - startX;
|
||||
double aby = y - startY;
|
||||
double abs = Math.abs(abx*nx+aby*ny);
|
||||
if (abs < 3) return k;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void drawArrow(Picture p, int startx, int starty, int endx, int endy) {
|
||||
|
||||
double deltax = startx - endx;
|
||||
double result;
|
||||
|
||||
if (deltax == 0.0d) {
|
||||
result = (starty > endy ? Math.PI / 2 : -Math.PI / 2);
|
||||
}
|
||||
else {
|
||||
result = Math.atan((starty - endy) / deltax) + (startx < endx ? Math.PI : 0);
|
||||
}
|
||||
|
||||
double angle = result;
|
||||
double arrowAngle = Math.PI / 8.0d;
|
||||
double arrowSize = 10;
|
||||
double x1 = arrowSize * Math.cos(angle - arrowAngle);
|
||||
double y1 = arrowSize * Math.sin(angle - arrowAngle);
|
||||
double x2 = arrowSize * Math.cos(angle + arrowAngle);
|
||||
double y2 = arrowSize * Math.sin(angle + arrowAngle);
|
||||
double cx = (arrowSize / 2.0f) * Math.cos(angle);
|
||||
double cy = (arrowSize / 2.0f) * Math.sin(angle);
|
||||
int x[] = {(int) endx, (int) (endx+x1), (int) (endx+x2), (int) endx};
|
||||
int y[] = {(int) endy, (int) (endy+y1), (int) (endy+y2), (int) endy};
|
||||
p.line(startx, starty, endx, endy);
|
||||
p.polygon(x,y);
|
||||
|
||||
}
|
||||
|
||||
private String darker(String color) {
|
||||
String red = color.substring(0, 2);
|
||||
String green = color.substring(2,4);
|
||||
String blue = color.substring(4,6);
|
||||
long r = Long.parseLong(red,16)/2;
|
||||
long g = Long.parseLong(green,16) /2;
|
||||
long b = Long.parseLong(blue,16) / 2;
|
||||
String sr = "0"+Long.toHexString(r);
|
||||
String sg = "0"+Long.toHexString(g);
|
||||
String sb = "0"+Long.toHexString(b);
|
||||
return sr.substring(sr.length()-2)+sg.substring(sg.length()-2)+sb.substring(sb.length()-2);
|
||||
}
|
||||
|
||||
private String brighter(String color) {
|
||||
String red = color.substring(0, 2);
|
||||
String green = color.substring(2,4);
|
||||
String blue = color.substring(4,6);
|
||||
long r = (Long.parseLong(red,16)+255)/2;
|
||||
long g = (Long.parseLong(green,16)) /2;
|
||||
long b = (Long.parseLong(blue,16)) / 2;
|
||||
String sr = "0"+Long.toHexString(r);
|
||||
String sg = "0"+Long.toHexString(g);
|
||||
String sb = "0"+Long.toHexString(b);
|
||||
return sr.substring(sr.length()-2)+sg.substring(sg.length()-2)+sb.substring(sb.length()-2);
|
||||
}
|
||||
|
||||
private String format(double d) {
|
||||
if((int) d == d) {
|
||||
return ""+(int) d;
|
||||
} else {
|
||||
return ""+d;
|
||||
}
|
||||
}
|
||||
|
||||
public Picture updateImage() {
|
||||
Knoten restrictToKnoten = null;
|
||||
Kante restrictToKante = null;
|
||||
if(restrictTo != null && restrictTo instanceof Knoten) restrictToKnoten = (Knoten) restrictTo;
|
||||
if(restrictTo != null && restrictTo instanceof Kante) restrictToKante = (Kante) restrictTo;
|
||||
|
||||
List<Knoten> knoten = graph.getAlleKnoten();
|
||||
List<Kante> kanten = graph.getAlleKanten();
|
||||
|
||||
int maxx = Integer.MIN_VALUE; int maxy = Integer.MIN_VALUE;
|
||||
int minx = Integer.MAX_VALUE; int miny = Integer.MAX_VALUE;
|
||||
for(Knoten k: knoten) {
|
||||
maxx = Math.max(maxx,k.getX());
|
||||
minx = Math.min(minx,k.getX());
|
||||
maxy = Math.max(maxy,k.getY());
|
||||
miny = Math.min(miny,k.getY());
|
||||
}
|
||||
|
||||
Picture p = new Picture(2000,2000,"FFFFE8");
|
||||
|
||||
if(restrictToKnoten != null) {
|
||||
knoten = graph.getNachbarknoten(restrictToKnoten);
|
||||
kanten = graph.getAusgehendeKanten(restrictToKnoten);
|
||||
knoten.add(restrictToKnoten);
|
||||
// this.getContent().setTranslateY(this.getHeight()/2-restrictToKnoten.getY());
|
||||
// this.getContent().setTranslateX(this.getWidth()/2-restrictToKnoten.getX());
|
||||
this.getContent().setTranslateY(1000-(restrictToKnoten.getY()));
|
||||
this.getContent().setTranslateX(1000-(restrictToKnoten.getX()));
|
||||
} else if (restrictToKante != null ) {
|
||||
kanten.clear();
|
||||
kanten.add(restrictToKante);
|
||||
knoten.clear();
|
||||
knoten.add(restrictToKante.getStart());
|
||||
knoten.add(restrictToKante.getZiel());
|
||||
// this.getContent().setTranslateY(this.getHeight()/2-restrictToKnoten.getY());
|
||||
// this.getContent().setTranslateX(this.getWidth()/2-restrictToKnoten.getX());
|
||||
this.getContent().setTranslateX(1000-(restrictToKante.getStart().getX()+restrictToKante.getZiel().getX())/2);
|
||||
this.getContent().setTranslateY(1000-(restrictToKante.getStart().getY()+restrictToKante.getZiel().getY())/2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*this.getContent().setTranslateX(1000-(minx+maxx)/2);
|
||||
this.getContent().setTranslateY(1000-(miny+maxy)/2);*/
|
||||
}
|
||||
p.textMode(Picture.CENTER);
|
||||
|
||||
if(options.bildAnzeigen && !options.bildDatei.isEmpty()) {
|
||||
Picture p2 = new Picture("./images/"+options.bildDatei);
|
||||
p.getImage().getGraphics().drawImage(p2.getImage(), 0, 0, null);
|
||||
minx = options.vertexSize;
|
||||
miny = options.vertexSize;
|
||||
maxx = p2.getWidth()-options.vertexSize;
|
||||
maxy = p2.getHeight()-options.vertexSize;
|
||||
}
|
||||
|
||||
// Zone in der Mitte markieren
|
||||
if(restrictToKnoten!=null) {
|
||||
p.fill("FFE8E8");
|
||||
p.stroke("FFE8E8");
|
||||
p.ellipse(restrictToKnoten.getX(), restrictToKnoten.getY(), options.vertexSize*2, options.vertexSize*2);
|
||||
}
|
||||
if(restrictToKante!=null) {
|
||||
p.fill("FFE8E8");
|
||||
p.stroke("FFE8E8");
|
||||
p.strokeWeight(30);
|
||||
p.line(restrictToKante.getStart().getX(), restrictToKante.getStart().getY(), restrictToKante.getZiel().getX(),restrictToKante.getZiel().getY());
|
||||
}
|
||||
|
||||
for (Kante k : kanten) {
|
||||
if (!options.farbenKanten[k.getFarbe()].equals("invisible") || selected.contains(k)) {
|
||||
|
||||
double startX = k.getStart().getX();
|
||||
double startY = k.getStart().getY();
|
||||
double endX = k.getZiel().getX();
|
||||
double endY = k.getZiel().getY();
|
||||
double dy = (endY-startY);
|
||||
double dx = (endX-startX);
|
||||
double l = Math.sqrt(dx*dx+dy*dy);
|
||||
dy = dy /l; dx = dx / l;
|
||||
startX += dx * (options.vertexSize/2+1);
|
||||
startY += dy * (options.vertexSize/2+1);
|
||||
endX -= dx * (options.vertexSize/2+1);
|
||||
endY -= dy * (options.vertexSize/2+1);
|
||||
double dx2 = dy*5;
|
||||
double dy2 = -dx*5;
|
||||
if (graph.isGerichtet() && graph.getKante(k.getZiel(), k.getStart())!=null){
|
||||
startX += dx2;
|
||||
startY += dy2;
|
||||
endX += dx2;
|
||||
endY += dy2;
|
||||
}
|
||||
|
||||
if(selected.contains(k)) {
|
||||
p.stroke("FF0000");
|
||||
p.strokeWeight(4);
|
||||
p.line((int) startX, (int) startY, (int) endX, (int) endY);
|
||||
}
|
||||
if (!options.farbenKanten[k.getFarbe()].equals("invisible")){
|
||||
p.stroke(options.farbenKanten[k.getFarbe()]);
|
||||
p.fill(options.farbenKanten[k.getFarbe()]);
|
||||
}
|
||||
else
|
||||
{
|
||||
p.stroke("505050");
|
||||
p.fill("505050");
|
||||
}
|
||||
|
||||
p.strokeWeight(2);
|
||||
|
||||
if(graph.isGerichtet()) {
|
||||
drawArrow(p, (int) startX, (int) startY, (int) endX, (int) endY);
|
||||
} else {
|
||||
p.line((int) startX, (int) startY, (int) endX, (int) endY);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Kante k : kanten) {
|
||||
if (!options.farbenKanten[k.getFarbe()].equals("invisible") || selected.contains(k)) {
|
||||
double startX = k.getStart().getX();
|
||||
double startY = k.getStart().getY();
|
||||
double endX = k.getZiel().getX();
|
||||
double endY = k.getZiel().getY();
|
||||
double dy = (endY-startY);
|
||||
double dx = (endX-startX);
|
||||
double l = Math.sqrt(dx*dx+dy*dy);
|
||||
dy = dy /l; dx = dx / l;
|
||||
startX += dx * (options.vertexSize/2+1);
|
||||
startY += dy * (options.vertexSize/2+1);
|
||||
endX -= dx * (options.vertexSize/2+1);
|
||||
endY -= dy * (options.vertexSize/2+1);
|
||||
double dx2 = dy*5;
|
||||
double dy2 = -dx*5;
|
||||
|
||||
if(graph.isGerichtet()) {
|
||||
if (graph.getKante(k.getZiel(), k.getStart())!=null){
|
||||
startX += dx2;
|
||||
startY += dy2;
|
||||
endX += dx2;
|
||||
endY += dy2;
|
||||
}
|
||||
|
||||
}
|
||||
if(options.showEdgeWeights && graph.isGewichtet()) {
|
||||
double my = (startY+startY+endY)/3;
|
||||
double mx = (startX+startX+endX)/3;
|
||||
p.fill(255);
|
||||
p.stroke(0);
|
||||
p.strokeWeight(1);
|
||||
p.rect((int) mx-15, (int) my-7, 30, 16);
|
||||
p.fill(0);
|
||||
p.text(format(k.getGewicht()), (int) mx, (int) my);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Knoten k : knoten) {
|
||||
|
||||
p.fill(options.farbenKnoten[k.getFarbe()]);
|
||||
|
||||
p.stroke(darker(options.farbenKnoten[k.getFarbe()]));
|
||||
p.strokeWeight(3);
|
||||
p.ellipse(k.getX(), k.getY(), options.vertexSize, options.vertexSize);
|
||||
if(selected.contains(k)) {
|
||||
p.noFill();
|
||||
p.strokeWeight(2);
|
||||
p.stroke(255,0,0);
|
||||
p.ellipse(k.getX(), k.getY(), options.vertexSize+2, options.vertexSize+2);
|
||||
}
|
||||
|
||||
p.fill(0);
|
||||
p.stroke(0);
|
||||
p.strokeWeight(0);
|
||||
p.textMode(Picture.CENTER);
|
||||
if (options.showVertexText) {
|
||||
p.text(""+graph.getNummer(k), k.getX(), k.getY());
|
||||
} else {
|
||||
if (options.showVertexValue) {
|
||||
p.text(format(k.getDoubleWert()), k.getX(), k.getY());
|
||||
}
|
||||
}
|
||||
|
||||
// Knotenbezeichnung
|
||||
p.textMode(Picture.CORNER);
|
||||
p.fill("000080");
|
||||
if(options.showVertexInfo && !k.getInfotext().equals("")) {
|
||||
p.text(k.getInfotext(), k.getX()+options.vertexSize/2+5,k.getY());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.setImage(p, false);
|
||||
Picture zugeschnitten = new Picture(maxx-minx+2*options.vertexSize,maxy-miny+2*options.vertexSize);
|
||||
zugeschnitten.getImage().getGraphics().drawImage(p.getImage(), 0, 0, maxx-minx+2*options.vertexSize, maxy-miny+2*options.vertexSize, minx-options.vertexSize, miny-options.vertexSize, maxx+options.vertexSize, maxy+options.vertexSize, null);
|
||||
return zugeschnitten;
|
||||
}
|
||||
|
||||
|
||||
public GraphOptions getGraphOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Graphen zurueck.
|
||||
*
|
||||
* @return Graph
|
||||
*/
|
||||
public Graph getGraph() {
|
||||
return graph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt das selektierte Knotenobjekt zurueck.
|
||||
*
|
||||
* @return Object
|
||||
*/
|
||||
public Knoten getSelectedKnoten() {
|
||||
if(selected.size()==1 && selected.get(0) instanceof Knoten)
|
||||
return ((Knoten) (selected.get(0)));
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die selektierte KnotenobjektListe (als Array) zurueck.
|
||||
*
|
||||
* @return Object[]
|
||||
*/
|
||||
public List<Knoten> getSelectedKnotenListe() {
|
||||
List<Knoten> l = new ArrayList<Knoten>();
|
||||
for(GraphElement g : selected) {
|
||||
if(g instanceof Knoten) l.add((Knoten) g);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt das selektierte Kantenobjekt zurueck.
|
||||
*
|
||||
* @return Object
|
||||
*/
|
||||
public Kante getSelectedKante() {
|
||||
if(selected.size()==1 && selected.get(0) instanceof Kante)
|
||||
return ((Kante) (selected.get(0)));
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ueberschreibt die Methode toString. Eine String-Repraesentation des GraphPlotters wird ausgegeben.
|
||||
*
|
||||
* @return String Die String-Repraesentation des GraphPlotters
|
||||
*/
|
||||
public String toString() {
|
||||
String s = "";
|
||||
if(graph.isGerichtet())
|
||||
s += "Gerichteter, ";
|
||||
else
|
||||
s += "Ungerichteter, ";
|
||||
if(graph.isGewichtet())
|
||||
s += "gewichteter Graph mit Hintergrundbild: ";
|
||||
else
|
||||
s += "ungewichteter Graph mit Hintergrundbild: ";
|
||||
if(options.bildDatei.equals(""))
|
||||
s += " kein Bild!";
|
||||
else
|
||||
s += options.bildDatei + "!";
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die String-Repraesentation des GraphPlotters auf der Konsole aus.
|
||||
*/
|
||||
public void ausgabe() {
|
||||
System.out.println(toString() + "\n"+graph.toString());
|
||||
}
|
||||
// Ende Methoden
|
||||
}
|
||||
15
graph/Hilfe.ctxt
Normal file
15
graph/Hilfe.ctxt
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#BlueJ class context
|
||||
comment0.target=Hilfe
|
||||
comment1.params=
|
||||
comment1.target=void\ loescheAlles()
|
||||
comment2.params=text
|
||||
comment2.target=void\ append(java.lang.String)
|
||||
comment3.params=
|
||||
comment3.target=void\ indentMore()
|
||||
comment4.params=
|
||||
comment4.target=void\ indentLess()
|
||||
comment5.params=gp
|
||||
comment5.target=void\ setGraphPlotter(GraphPlotter)
|
||||
comment6.params=a
|
||||
comment6.target=void\ setReviewAllowed(boolean)
|
||||
numComments=7
|
||||
17
graph/Hilfe.java
Normal file
17
graph/Hilfe.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package graph;
|
||||
|
||||
|
||||
public interface Hilfe {
|
||||
|
||||
public abstract void loescheAlles();
|
||||
|
||||
public abstract void append(String text);
|
||||
|
||||
public void indentMore() ;
|
||||
|
||||
public void indentLess() ;
|
||||
|
||||
public void setGraphPlotter(GraphPlotter gp);
|
||||
|
||||
public void setReviewAllowed(boolean a);
|
||||
}
|
||||
64
graph/Kante.ctxt
Normal file
64
graph/Kante.ctxt
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#BlueJ class context
|
||||
comment0.target=Kante
|
||||
comment0.text=\r\n\ Die\ Klasse\ Kante\ beschreibt\ die\ Datenstruktur\ einer\ Kante,\ bestehend\ aus\ Startknoten,\ Gewicht\ und\ Zielknoten.\r\n\ Da\ Kanten\ innerhalb\ von\ Adjazenzlisten\ und\ -Matrizen\ repraesentiert\ werden,\ ist\ diese\ Klasse\ eigentlich\ unnoetig\!\r\n\ Sie\ wurde\ zum\ Zweck\ der\ Vereinfachung\ -\ sozusagen\ als\ Zwischenspeicher\ von\ Kanten\ -\ eingefuehrt.\r\n\ Auch\ soll\ sie\ das\ Kantengewicht\ verwalten\ und\ Aufschluss\ darueber\ geben,\ ob\ sie\ gefaerbt/geloescht\ ist\ oder\ nicht.\r\n\ \r\n\ @author\ \ Dirk\ Zechnall,\ Thomas\ Schaller\r\n\ @version\ 22.07.2020\ (v6.4)\r\n
|
||||
comment1.params=neuerStart\ neuerZiel\ neuesGewicht
|
||||
comment1.target=Kante(Knoten,\ Knoten,\ double)
|
||||
comment1.text=\r\n\ Der\ Konstruktor\ erstellt\ eine\ neue\ Kante\ mit\ Start-\ und\ Zielknoten\ und\ Kantengewicht.\r\n\ Die\ Kante\ ist\ zu\ Beginn\ ungefaerbt.\r\n\r\n\ @param\ \ neuerStart\ \ Der\ neue\ Startknoten\r\n\ @param\ \ neuerZiel\ \ Der\ neue\ Zielknoten\r\n\ @param\ \ neuesGewicht\ \ Das\ neue\ Kantengewicht\r\n
|
||||
comment10.params=
|
||||
comment10.target=Knoten\ getZiel()
|
||||
comment10.text=\r\n\ Gibt\ den\ Zielknoten\ der\ Kante\ zurueck\r\n\ \r\n\ @return\ \ Zielknoten\r\n
|
||||
comment11.params=k
|
||||
comment11.target=Knoten\ getAnderesEnde(Knoten)
|
||||
comment11.text=\r\n\ Gibt\ Knoten\ am\ anderen\ Ende\ der\ Kante\ zurueck\r\n\ @param\ k\ Knoten\ am\ ersten\ Ende\ der\ Kante\r\n\ @return\ \ Knoten\ am\ anderen\ Ende\r\n
|
||||
comment12.params=wert
|
||||
comment12.target=void\ setMarkiert(boolean)
|
||||
comment12.text=\r\n\ Setzt\ das\ markiert-Attribut\ der\ Kante\r\n\r\n\ @param\ \ wert\ \ Der\ neu\ zu\ setzende\ markiert-Wert\r\n
|
||||
comment13.params=
|
||||
comment13.target=boolean\ isMarkiert()
|
||||
comment13.text=\r\n\ Gibt\ zur\u00FCck,\ ob\ die\ Kanten\ markiert\ ist\r\n\ \r\n\ @return\ \ markiert?\r\n
|
||||
comment14.params=wert
|
||||
comment14.target=void\ setGeloescht(boolean)
|
||||
comment14.text=\r\n\ Setzt\ das\ gel\u00F6scht-Attribut\ der\ Kante\r\n\r\n\ @param\ \ wert\ \ Der\ neu\ zu\ setzende\ gel\u00F6scht-Wert\r\n
|
||||
comment15.params=
|
||||
comment15.target=boolean\ isGeloescht()
|
||||
comment15.text=\r\n\ Gibt\ den\ gel\u00F6scht-Wert\ der\ Kante\ zurueck\r\n\ \r\n\ @return\ \ gel\u00F6scht?\r\n
|
||||
comment16.params=
|
||||
comment16.target=int\ getFarbe()
|
||||
comment16.text=\r\n\ Gibt\ zurueck,\ in\ welcher\ Farbe\ die\ Kante\ gezeichnet\ werden\ soll.\r\n\ Ist\ die\ Farbe\ nicht\ gesetzt,\ dann\ wird\ eine\ unmarkierte\ Kante\ in\ Farbe\ 1\ \r\n\ und\ eine\ markierte\ in\ Farbe\ 2\ gezeichnet.\r\n\ @return\ Nummer\ der\ Farbe\r\n
|
||||
comment17.params=farbe
|
||||
comment17.target=void\ setFarbe(int)
|
||||
comment17.text=\r\n\ Setzt\ die\ Farbe\ auf\ einen\ bestimmten\ Farbindex\r\n\ @param\ farbe\ Index\ der\ Farbe\ (0-19)\r\n
|
||||
comment18.params=
|
||||
comment18.target=void\ setStandardFarbe()
|
||||
comment18.text=\r\n\ Setzt\ die\ Farbe\ auf\ die\ Standardfarbgebung\ zur\u00FCck\r\n
|
||||
comment19.params=e
|
||||
comment19.target=int\ compareTo(GraphElement)
|
||||
comment19.text=\ Vergleicht\ die\ Kante\ mit\ einer\ anderen\ Kante\ bez\u00FCglich\ ihres\ Gewichts\r\n\ @param\ e\ andere\ Kante\r\n\ @return\ kleiner\ 0\ die\ andere\ Kante\ hat\ ein\ gr\u00F6\u00DFeres\ Gewicht,\ gr\u00F6\u00DFer\ 0\ die\ andere\ Kante\ hat\ ein\ kleineres\ Gewicht,\ gleich\ 0\ beides\ sind\ gleich\r\n
|
||||
comment2.params=
|
||||
comment2.target=void\ init()
|
||||
comment2.text=\r\n\ Die\ Methode\ init\ initialisiert\ die\ Kantenfaerbung\ (auf\ unmarkiert)\r\n
|
||||
comment20.params=
|
||||
comment20.target=java.lang.String\ toString()
|
||||
comment20.text=\r\n\ Die\ Methode\ ueberschreibt\ die\ Methode\ toString()\ und\ gibt\ die\ String-Raepraesentation\ einer\ Kante\ zurueck\r\n\ \r\n\ @return\ \ \ \ \ \ String-Raepraesentation\ der\ Kante\r\n
|
||||
comment3.params=status
|
||||
comment3.target=void\ setStatus(java.lang.String)
|
||||
comment3.text=\r\n\ Setzt\ den\ Status\ einer\ Kante,\ der\ in\ einem\ String\ gespeichert\ ist.\r\n\ Form\:\ markiert,geloescht,farbe\ \r\n\ Dabei\ sind\ markiert\ und\ geloescht\ boolsche\ Werte\ (0\ \=\ false,\ 1\ \=\ true)\ und\r\n\ die\ farbe\ eine\ Zahl\r\n\ @param\ status\ \ Statusstring\r\n
|
||||
comment4.params=
|
||||
comment4.target=java.lang.String\ getStatus()
|
||||
comment4.text=\r\n\ Liefert\ den\ Status\ einer\ Kante\ als\ String.\r\n\ Form\:\ markiert,geloescht,farbe\ \r\n\ Dabei\ sind\ markiert\ und\ geloescht\ boolsche\ Werte\ (0\ \=\ false,\ 1\ \=\ true)\ und\r\n\ die\ farbe\ eine\ Zahl\r\n\ @return\ Statusstring\r\n
|
||||
comment5.params=neuesGewicht
|
||||
comment5.target=void\ setGewicht(double)
|
||||
comment5.text=\r\n\ Setzt\ das\ Gewicht\ der\ Kante\r\n\r\n\ @param\ \ neuesGewicht\ \ Das\ neu\ zu\ setzende\ Gewicht\r\n
|
||||
comment6.params=
|
||||
comment6.target=double\ getGewicht()
|
||||
comment6.text=\r\n\ Gibt\ das\ Gewicht\ der\ Kante\ zurueck\r\n\ \r\n\ @return\ \ Gewicht\ der\ Kante\r\n
|
||||
comment7.params=neuerSatrtKnoten
|
||||
comment7.target=void\ setStart(Knoten)
|
||||
comment7.text=\r\n\ Setzt\ den\ Startknoten\ der\ Kante\r\n\r\n\ @param\ \ neuerSatrtKnoten\ \ Der\ neu\ zu\ setzende\ Startknoten\r\n
|
||||
comment8.params=
|
||||
comment8.target=Knoten\ getStart()
|
||||
comment8.text=\r\n\ Gibt\ den\ Startknoten\ der\ Kante\ zurueck\r\n\ \r\n\ @return\ \ Startknoten\r\n
|
||||
comment9.params=neuerZielKnoten
|
||||
comment9.target=void\ setZiel(Knoten)
|
||||
comment9.text=\r\n\ Setzt\ den\ Zielknoten\ der\ Kante\r\n\r\n\ @param\ \ neuerZielKnoten\ \ Der\ neu\ zu\ setzende\ Zielknoten\r\n
|
||||
numComments=21
|
||||
225
graph/Kante.java
Normal file
225
graph/Kante.java
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
package graph;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* Die Klasse Kante beschreibt die Datenstruktur einer Kante, bestehend aus Startknoten, Gewicht und Zielknoten.
|
||||
* Da Kanten innerhalb von Adjazenzlisten und -Matrizen repraesentiert werden, ist diese Klasse eigentlich unnoetig!
|
||||
* Sie wurde zum Zweck der Vereinfachung - sozusagen als Zwischenspeicher von Kanten - eingefuehrt.
|
||||
* Auch soll sie das Kantengewicht verwalten und Aufschluss darueber geben, ob sie gefaerbt/geloescht ist oder nicht.
|
||||
*
|
||||
* @author Dirk Zechnall, Thomas Schaller
|
||||
* @version 22.07.2020 (v6.4)
|
||||
*/
|
||||
public class Kante extends GraphElement
|
||||
{
|
||||
private Knoten start;
|
||||
private Knoten ziel;
|
||||
private double gewicht;
|
||||
private boolean markiert = false;
|
||||
private boolean geloescht = false;
|
||||
private int farbe = -1;
|
||||
|
||||
/**
|
||||
* Der Konstruktor erstellt eine neue Kante mit Start- und Zielknoten und Kantengewicht.
|
||||
* Die Kante ist zu Beginn ungefaerbt.
|
||||
*
|
||||
* @param neuerStart Der neue Startknoten
|
||||
* @param neuerZiel Der neue Zielknoten
|
||||
* @param neuesGewicht Das neue Kantengewicht
|
||||
*/
|
||||
public Kante (Knoten neuerStart, Knoten neuerZiel, double neuesGewicht) {
|
||||
gewicht = neuesGewicht;
|
||||
start = neuerStart;
|
||||
ziel = neuerZiel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Methode init initialisiert die Kantenfaerbung (auf unmarkiert)
|
||||
*/
|
||||
protected void init() {
|
||||
markiert = false;
|
||||
geloescht = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Status einer Kante, der in einem String gespeichert ist.
|
||||
* Form: markiert,geloescht,farbe
|
||||
* Dabei sind markiert und geloescht boolsche Werte (0 = false, 1 = true) und
|
||||
* die farbe eine Zahl
|
||||
* @param status Statusstring
|
||||
*/
|
||||
public void setStatus(String status) {
|
||||
List<String> items = Arrays.asList(status.split("\\s*,\\s*"));
|
||||
this.markiert = items.get(0).equals("1");
|
||||
this.geloescht = items.get(1).equals("1");
|
||||
this.farbe = Integer.parseInt(items.get(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert den Status einer Kante als String.
|
||||
* Form: markiert,geloescht,farbe
|
||||
* Dabei sind markiert und geloescht boolsche Werte (0 = false, 1 = true) und
|
||||
* die farbe eine Zahl
|
||||
* @return Statusstring
|
||||
*/
|
||||
public String getStatus() {
|
||||
return ""+(markiert ? "1," : "0,")+ (geloescht ? "1," : "0,")+ farbe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt das Gewicht der Kante
|
||||
*
|
||||
* @param neuesGewicht Das neu zu setzende Gewicht
|
||||
*/
|
||||
public void setGewicht(double neuesGewicht) {
|
||||
gewicht = neuesGewicht;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt das Gewicht der Kante zurueck
|
||||
*
|
||||
* @return Gewicht der Kante
|
||||
*/
|
||||
public double getGewicht() {
|
||||
return gewicht;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Startknoten der Kante
|
||||
*
|
||||
* @param neuerSatrtKnoten Der neu zu setzende Startknoten
|
||||
*/
|
||||
public void setStart(Knoten neuerSatrtKnoten) {
|
||||
start = neuerSatrtKnoten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Startknoten der Kante zurueck
|
||||
*
|
||||
* @return Startknoten
|
||||
*/
|
||||
public Knoten getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Zielknoten der Kante
|
||||
*
|
||||
* @param neuerZielKnoten Der neu zu setzende Zielknoten
|
||||
*/
|
||||
public void setZiel(Knoten neuerZielKnoten) {
|
||||
ziel = neuerZielKnoten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Zielknoten der Kante zurueck
|
||||
*
|
||||
* @return Zielknoten
|
||||
*/
|
||||
public Knoten getZiel() {
|
||||
return ziel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt Knoten am anderen Ende der Kante zurueck
|
||||
* @param k Knoten am ersten Ende der Kante
|
||||
* @return Knoten am anderen Ende
|
||||
*/
|
||||
public Knoten getAnderesEnde(Knoten k) {
|
||||
if (k == start) return ziel;
|
||||
if (k == ziel) return start;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt das markiert-Attribut der Kante
|
||||
*
|
||||
* @param wert Der neu zu setzende markiert-Wert
|
||||
*/
|
||||
public void setMarkiert(boolean wert) {
|
||||
markiert = wert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt zurück, ob die Kanten markiert ist
|
||||
*
|
||||
* @return markiert?
|
||||
*/
|
||||
public boolean isMarkiert() {
|
||||
return markiert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt das gelöscht-Attribut der Kante
|
||||
*
|
||||
* @param wert Der neu zu setzende gelöscht-Wert
|
||||
*/
|
||||
public void setGeloescht(boolean wert) {
|
||||
geloescht = wert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den gelöscht-Wert der Kante zurueck
|
||||
*
|
||||
* @return gelöscht?
|
||||
*/
|
||||
public boolean isGeloescht() {
|
||||
return geloescht;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt zurueck, in welcher Farbe die Kante gezeichnet werden soll.
|
||||
* Ist die Farbe nicht gesetzt, dann wird eine unmarkierte Kante in Farbe 1
|
||||
* und eine markierte in Farbe 2 gezeichnet.
|
||||
* @return Nummer der Farbe
|
||||
*/
|
||||
public int getFarbe() {
|
||||
if(farbe == -1) {
|
||||
if(geloescht) return 2;
|
||||
if(markiert) return 1;
|
||||
return 0;
|
||||
}
|
||||
return farbe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die Farbe auf einen bestimmten Farbindex
|
||||
* @param farbe Index der Farbe (0-19)
|
||||
*/
|
||||
public void setFarbe(int farbe) {
|
||||
if(farbe>=0 && farbe < 20)
|
||||
this.farbe = farbe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die Farbe auf die Standardfarbgebung zurück
|
||||
*/
|
||||
|
||||
public void setStandardFarbe() {
|
||||
farbe = -1;
|
||||
}
|
||||
|
||||
/** Vergleicht die Kante mit einer anderen Kante bezüglich ihres Gewichts
|
||||
* @param e andere Kante
|
||||
* @return kleiner 0 die andere Kante hat ein größeres Gewicht, größer 0 die andere Kante hat ein kleineres Gewicht, gleich 0 beides sind gleich
|
||||
*/
|
||||
public int compareTo(GraphElement e) {
|
||||
double w1, w2;
|
||||
if(e instanceof Knoten) w1 = ((Knoten) e).getDoubleWert(); else w1 = ((Kante) e).getGewicht();
|
||||
w2 = getGewicht();
|
||||
return (int) (w2-w1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Methode ueberschreibt die Methode toString() und gibt die String-Raepraesentation einer Kante zurueck
|
||||
*
|
||||
* @return String-Raepraesentation der Kante
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return " --("+gewicht+")--> ";
|
||||
}
|
||||
|
||||
}
|
||||
76
graph/Knoten.ctxt
Normal file
76
graph/Knoten.ctxt
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#BlueJ class context
|
||||
comment0.target=Knoten
|
||||
comment0.text=\r\n\ Diese\ Klasse\ Knoten\ definiert\ einen\ Knoten.\r\n\ Knoten\ haben\ eine\ Position,\ eine\ Farbe\ und\ einen\ Wert\ f\u00FCr\ sonstige\ Codierungszwecke\ und\ sind\ markiert\ und/oder\ besucht.\r\n\ Im\ Infotext\ kann\ eine\ zus\u00E4tzliche\ Information\ f\u00FCr\ die\ Anzeige\ gespeichert\ werden.\r\n\ \r\n\ @author\ Dirk\ Zechnall,\ Thomas\ Schaller\r\n\ @version\ 22.07.2020\ (v6.4)\r\n
|
||||
comment1.params=x\ y
|
||||
comment1.target=Knoten(int,\ int)
|
||||
comment1.text=\r\n\ Der\ Konstruktor\ erstellt\ einen\ neuen\ Knoten\ mit\ einem\ neuen\ Namen\r\n\r\n\ @param\ \ x\ \ x-Position\ des\ Knotens\r\n\ @param\ \ y\ \ y-Position\ des\ Knotens\r\n
|
||||
comment10.params=
|
||||
comment10.target=double\ getDoubleWert()
|
||||
comment10.text=\r\n\ Gibt\ den\ Wert\ vom\ Knoten\ als\ Double-Wert\ zurueck\r\n\ \r\n\ @return\ \ Wert\ des\ Knotens\r\n
|
||||
comment11.params=markiert
|
||||
comment11.target=void\ setMarkiert(boolean)
|
||||
comment11.text=\r\n\ Setzt\ das\ Markiertattribut\ vom\ Knoten\r\n\r\n\ @param\ \ markiert\ \ Der\ neu\ zu\ setzende\ Markiertwert\r\n
|
||||
comment12.params=
|
||||
comment12.target=boolean\ isMarkiert()
|
||||
comment12.text=\r\n\ Gibt\ den\ Markiertwert\ vom\ Knoten\ zurueck\r\n\ \r\n\ @return\ \ markiert?\r\n
|
||||
comment13.params=markiert
|
||||
comment13.target=void\ setBesucht(boolean)
|
||||
comment13.text=\r\n\ Setzt\ das\ Besuchtattribut\ vom\ Knoten\r\n\r\n\ @param\ \ markiert\ \ Der\ neu\ zu\ setzende\ Besuchtwert\r\n
|
||||
comment14.params=
|
||||
comment14.target=boolean\ isBesucht()
|
||||
comment14.text=\r\n\ Gibt\ den\ Besuchtwert\ vom\ Knoten\ zurueck\r\n\ \r\n\ @return\ \ besucht?\r\n
|
||||
comment15.params=
|
||||
comment15.target=int\ getFarbe()
|
||||
comment15.text=\r\n\ Gibt\ den\ Index\ der\ Farbe\ des\ Knoten\ zur\u00FCck.\r\n\ Standardm\u00E4\u00DFig\ h\u00E4ngt\ die\ Farbe\ von\ den\ Attributen\ markiert\ und\ besucht\ ab.\r\n\ Durch\ Setzen\ der\ Farbe\ kann\ die\ Farbe\ gezielt\ gesetzt\ werden.\r\n\ @return\ Farbe\ des\ Knotens\r\n
|
||||
comment16.params=farbe
|
||||
comment16.target=void\ setFarbe(int)
|
||||
comment16.text=\r\n\ Setzt\ den\ Index\ der\ Farbe\ des\ Knoten.\r\n\ Standardm\u00E4\u00DFig\ h\u00E4ngt\ die\ Farbe\ von\ den\ Attributen\ markiert,\ besucht\ und\ beendet\ ab.\r\n\ Durch\ Setzen\ der\ Farbe\ kann\ die\ Farbe\ gezielt\ gesetzt\ werden.\r\n\ @param\ farbe\ Index\ der\ Farbe\ (0-19)\r\n
|
||||
comment17.params=
|
||||
comment17.target=boolean\ isFarbeAutomatisch()
|
||||
comment17.text=\ Gibt\ zur\u00FCck,\ ob\ die\ Knotenfarbe\ automatisch\ aus\ den\ Attributen\ ermittelt\ wird.\r\n\ @return\ true\=Farbe\ wird\ automatisch\ bestimmt,\ false\=Farbe\ wurde\ explizit\ gesetzt.\r\n\ \ \ \ \ \r\n
|
||||
comment18.params=auto
|
||||
comment18.target=void\ setFarbeAutomatisch(boolean)
|
||||
comment18.text=\ Legt\ fest,\ ob\ die\ Knotenfarbe\ automatisch\ aus\ den\ Attributen\ ermittelt\ wird.\r\n\ @param\ auto\ true\=Farbe\ wird\ automatisch\ bestimmt,\r\n\ \ \ \ \ \ \ \ \ \ \ \ \ false\=Farbe\ wird\ explizit\ gesetzt.\r\n
|
||||
comment19.params=
|
||||
comment19.target=int\ getX()
|
||||
comment19.text=\ Liefert\ die\ x-Position\ des\ Knotens\r\n\ @return\ x-Postion\r\n
|
||||
comment2.params=x\ y\ neuerWert
|
||||
comment2.target=Knoten(int,\ int,\ double)
|
||||
comment2.text=\r\n\ Der\ Konstruktor\ erstellt\ einen\ neuen\ Knoten\ mit\ einem\ Startwert\r\n\r\n\ @param\ \ x\ \ x-Position\ des\ Knotens\r\n\ @param\ \ y\ \ y-Position\ des\ Knotens\ \ \ \ \r\n\ @param\ \ neuerWert\ \ Der\ neue\ Wert\ des\ Knotens\ \r\n
|
||||
comment20.params=
|
||||
comment20.target=int\ getY()
|
||||
comment20.text=\ Liefert\ die\ y-Position\ des\ Knotens\r\n\ @return\ y-Postion\r\n
|
||||
comment21.params=x
|
||||
comment21.target=void\ setX(int)
|
||||
comment21.text=\ Setzt\ die\ x-Position\ des\ Knotens\r\n\ @param\ x\ x-Postion\r\n
|
||||
comment22.params=y
|
||||
comment22.target=void\ setY(int)
|
||||
comment22.text=\ Setzt\ die\ y-Position\ des\ Knotens\r\n\ @param\ y\ y-Postion\r\n
|
||||
comment23.params=e
|
||||
comment23.target=int\ compareTo(GraphElement)
|
||||
comment23.text=\ Vergleicht\ den\ Knoten\ mit\ einem\ anderen\ Knoten\ bez\u00FCglich\ seines\ Werts\r\n\ @param\ e\ anderer\ Knoten\r\n\ @return\ kleiner\ 0\ der\ andere\ Knoten\ hat\ einen\ gr\u00F6\u00DFeren\ Wert,\ gr\u00F6\u00DFer\ 0\ der\ andere\ Knoten\ hat\ einen\ kleineren\ Wert,\ gleich\ 0\ beide\ sind\ gleich\r\n
|
||||
comment24.params=
|
||||
comment24.target=java.lang.String\ toString()
|
||||
comment24.text=\r\n\ Die\ Methode\ ueberschreibt\ die\ Methode\ toString()\ und\ gibt\ die\ String-Raepraesentation\ eines\ Knotens\ zurueck\r\n\ \r\n\ @return\ \ \ \ \ \ String-Raepraesentation\ des\ Knotens\r\n
|
||||
comment3.params=status
|
||||
comment3.target=void\ setStatus(java.lang.String)
|
||||
comment3.text=\r\n\ Setzt\ den\ Status\ eines\ Knotens\ aus\ einem\ Status-String\r\n\ Format\:\ wert,markiert,besucht,farbe\r\n\ wobei\ wert\ eine\ double-Zahl,\ mariert\ und\ besucht\ ein\ boolean-Wert\ (0\=false,\ 1\ \=\ true)\ und\r\n\ farbe\ eine\ zahl\ ist.\r\n\r\n\ @param\ \ status\ Der\ Statusstring\r\n
|
||||
comment4.params=
|
||||
comment4.target=java.lang.String\ getStatus()
|
||||
comment4.text=\r\n\ Liefert\ den\ Status\ eines\ Knotens\ als\ Status-String\r\n\ Format\:\ wert,markiert,besucht,farbe\r\n\ wobei\ wert\ eine\ double-Zahl,\ mariert\ und\ besucht\ ein\ boolean-Wert\ (0\=false,\ 1\ \=\ true)\ und\r\n\ farbe\ eine\ zahl\ ist.\r\n\r\n\ @return\ Der\ Statusstring\r\n
|
||||
comment5.params=
|
||||
comment5.target=void\ init()
|
||||
comment5.text=\r\n\ Die\ Methode\ init\ initialisiert\ den\ Zustand\ eines\ Knotens\r\n
|
||||
comment6.params=infotext
|
||||
comment6.target=void\ setInfotext(java.lang.String)
|
||||
comment6.text=\ Setzt\ den\ Infotext\ f\u00FCr\ einen\ Knoten\r\n\ @param\ infotext\ Der\ neue\ Text\r\n
|
||||
comment7.params=
|
||||
comment7.target=java.lang.String\ getInfotext()
|
||||
comment7.text=\ Liefert\ den\ Infotext\ des\ Knotens\r\n\ @return\ Der\ Infotext\r\n
|
||||
comment8.params=neuerWert
|
||||
comment8.target=void\ setWert(double)
|
||||
comment8.text=\r\n\ Setzt\ den\ Wert\ beim\ Knoten\r\n\r\n\ @param\ \ neuerWert\ \ Der\ neu\ zu\ setzende\ Wert\r\n
|
||||
comment9.params=
|
||||
comment9.target=int\ getIntWert()
|
||||
comment9.text=\r\n\ Gibt\ den\ Wert\ vom\ Knoten\ als\ Integer-Wert\ zurueck\r\n\ \r\n\ @return\ \ Wert\ des\ Knotens\r\n
|
||||
numComments=25
|
||||
263
graph/Knoten.java
Normal file
263
graph/Knoten.java
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
package graph;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Diese Klasse Knoten definiert einen Knoten.
|
||||
* Knoten haben eine Position, eine Farbe und einen Wert für sonstige Codierungszwecke und sind markiert und/oder besucht.
|
||||
* Im Infotext kann eine zusätzliche Information für die Anzeige gespeichert werden.
|
||||
*
|
||||
* @author Dirk Zechnall, Thomas Schaller
|
||||
* @version 22.07.2020 (v6.4)
|
||||
*/
|
||||
public class Knoten extends GraphElement
|
||||
{
|
||||
private String infotext;
|
||||
private double wert; // wird z.B. fuer den Colorierungs-Algorithmus verwendet - speichert da die Farben (codiert als Zahlen)
|
||||
private boolean istMarkiert = false;
|
||||
private boolean istBesucht = false;
|
||||
private int x;
|
||||
private int y;
|
||||
private int farbe = -1;
|
||||
/**
|
||||
* Der Konstruktor erstellt einen neuen Knoten mit einem neuen Namen
|
||||
*
|
||||
* @param x x-Position des Knotens
|
||||
* @param y y-Position des Knotens
|
||||
*/
|
||||
public Knoten(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
wert = 0;
|
||||
infotext = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Der Konstruktor erstellt einen neuen Knoten mit einem Startwert
|
||||
*
|
||||
* @param x x-Position des Knotens
|
||||
* @param y y-Position des Knotens
|
||||
* @param neuerWert Der neue Wert des Knotens
|
||||
*/
|
||||
public Knoten(int x, int y, double neuerWert) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
wert = neuerWert;
|
||||
infotext = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Status eines Knotens aus einem Status-String
|
||||
* Format: wert,markiert,besucht,farbe
|
||||
* wobei wert eine double-Zahl, mariert und besucht ein boolean-Wert (0=false, 1 = true) und
|
||||
* farbe eine zahl ist.
|
||||
*
|
||||
* @param status Der Statusstring
|
||||
*/
|
||||
public void setStatus(String status) {
|
||||
List<String> items = Arrays.asList(status.split("\\s*,\\s*"));
|
||||
this.wert = Double.parseDouble(items.get(0)); // wird z.B. fuer den Colorierungs-Algorithmus verwendet - speichert da die Farben (codiert als Zahlen)
|
||||
this.istMarkiert = items.get(1).equals("1");
|
||||
this.istBesucht = items.get(2).equals("1");
|
||||
this.farbe = Integer.parseInt(items.get(3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert den Status eines Knotens als Status-String
|
||||
* Format: wert,markiert,besucht,farbe
|
||||
* wobei wert eine double-Zahl, mariert und besucht ein boolean-Wert (0=false, 1 = true) und
|
||||
* farbe eine zahl ist.
|
||||
*
|
||||
* @return Der Statusstring
|
||||
*/
|
||||
public String getStatus() {
|
||||
return ""+wert+","+(istMarkiert ? "1," : "0,")+ (istBesucht ? "1," : "0,")+ farbe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Methode init initialisiert den Zustand eines Knotens
|
||||
*/
|
||||
protected void init() {
|
||||
wert = 0.0;
|
||||
farbe = -1;
|
||||
istMarkiert = false;
|
||||
istBesucht = false;
|
||||
}
|
||||
|
||||
/** Setzt den Infotext für einen Knoten
|
||||
* @param infotext Der neue Text
|
||||
*/
|
||||
public void setInfotext(String infotext) {
|
||||
this.infotext = infotext;
|
||||
}
|
||||
|
||||
/** Liefert den Infotext des Knotens
|
||||
* @return Der Infotext
|
||||
*/
|
||||
public String getInfotext(){
|
||||
return infotext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Wert beim Knoten
|
||||
*
|
||||
* @param neuerWert Der neu zu setzende Wert
|
||||
*/
|
||||
public void setWert(double neuerWert) {
|
||||
wert = neuerWert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Wert vom Knoten als Integer-Wert zurueck
|
||||
*
|
||||
* @return Wert des Knotens
|
||||
*/
|
||||
public int getIntWert() {
|
||||
return (int) wert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Wert vom Knoten als Double-Wert zurueck
|
||||
*
|
||||
* @return Wert des Knotens
|
||||
*/
|
||||
public double getDoubleWert() {
|
||||
return wert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt das Markiertattribut vom Knoten
|
||||
*
|
||||
* @param markiert Der neu zu setzende Markiertwert
|
||||
*/
|
||||
public void setMarkiert(boolean markiert) {
|
||||
istMarkiert = markiert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Markiertwert vom Knoten zurueck
|
||||
*
|
||||
* @return markiert?
|
||||
*/
|
||||
public boolean isMarkiert() {
|
||||
return istMarkiert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt das Besuchtattribut vom Knoten
|
||||
*
|
||||
* @param markiert Der neu zu setzende Besuchtwert
|
||||
*/
|
||||
public void setBesucht(boolean markiert) {
|
||||
istBesucht = markiert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Besuchtwert vom Knoten zurueck
|
||||
*
|
||||
* @return besucht?
|
||||
*/
|
||||
public boolean isBesucht() {
|
||||
return istBesucht;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gibt den Index der Farbe des Knoten zurück.
|
||||
* Standardmäßig hängt die Farbe von den Attributen markiert und besucht ab.
|
||||
* Durch Setzen der Farbe kann die Farbe gezielt gesetzt werden.
|
||||
* @return Farbe des Knotens
|
||||
*/
|
||||
public int getFarbe() {
|
||||
if (farbe == -1) {
|
||||
int f = 0;
|
||||
if(istMarkiert) {
|
||||
f += 1;
|
||||
}
|
||||
if(istBesucht) {
|
||||
f += 2;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
return farbe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Index der Farbe des Knoten.
|
||||
* Standardmäßig hängt die Farbe von den Attributen markiert, besucht und beendet ab.
|
||||
* Durch Setzen der Farbe kann die Farbe gezielt gesetzt werden.
|
||||
* @param farbe Index der Farbe (0-19)
|
||||
*/
|
||||
|
||||
public void setFarbe(int farbe) {
|
||||
this.farbe = farbe;
|
||||
}
|
||||
|
||||
/** Gibt zurück, ob die Knotenfarbe automatisch aus den Attributen ermittelt wird.
|
||||
* @return true=Farbe wird automatisch bestimmt, false=Farbe wurde explizit gesetzt.
|
||||
|
||||
*/
|
||||
public boolean isFarbeAutomatisch() {
|
||||
return this.farbe == -1;
|
||||
}
|
||||
|
||||
/** Legt fest, ob die Knotenfarbe automatisch aus den Attributen ermittelt wird.
|
||||
* @param auto true=Farbe wird automatisch bestimmt,
|
||||
* false=Farbe wird explizit gesetzt.
|
||||
*/
|
||||
public void setFarbeAutomatisch(boolean auto) {
|
||||
if(auto) {
|
||||
farbe = -1;
|
||||
} else {
|
||||
if(farbe == -1) farbe = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Liefert die x-Position des Knotens
|
||||
* @return x-Postion
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Liefert die y-Position des Knotens
|
||||
* @return y-Postion
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/** Setzt die x-Position des Knotens
|
||||
* @param x x-Postion
|
||||
*/
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
/** Setzt die y-Position des Knotens
|
||||
* @param y y-Postion
|
||||
*/ public void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/** Vergleicht den Knoten mit einem anderen Knoten bezüglich seines Werts
|
||||
* @param e anderer Knoten
|
||||
* @return kleiner 0 der andere Knoten hat einen größeren Wert, größer 0 der andere Knoten hat einen kleineren Wert, gleich 0 beide sind gleich
|
||||
*/
|
||||
public int compareTo(GraphElement e) {
|
||||
double w1, w2;
|
||||
if(e instanceof Knoten) w1 = ((Knoten) e).getDoubleWert(); else w1 = ((Kante) e).getGewicht();
|
||||
w2 = getDoubleWert();
|
||||
return (int) (w2-w1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Methode ueberschreibt die Methode toString() und gibt die String-Raepraesentation eines Knotens zurueck
|
||||
*
|
||||
* @return String-Raepraesentation des Knotens
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "["+infotext+","+wert+","+istMarkiert+","+istBesucht+"]";
|
||||
}
|
||||
}
|
||||
110
graph/package.bluej
Normal file
110
graph/package.bluej
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#BlueJ package file
|
||||
dependency1.from=Graph
|
||||
dependency1.to=Knoten
|
||||
dependency1.type=UsesDependency
|
||||
dependency10.from=GraphPlotter
|
||||
dependency10.to=GraphOptions
|
||||
dependency10.type=UsesDependency
|
||||
dependency11.from=GraphPlotter
|
||||
dependency11.to=GraphElement
|
||||
dependency11.type=UsesDependency
|
||||
dependency12.from=GraphPlotter
|
||||
dependency12.to=Knoten
|
||||
dependency12.type=UsesDependency
|
||||
dependency13.from=GraphPlotter
|
||||
dependency13.to=Kante
|
||||
dependency13.type=UsesDependency
|
||||
dependency2.from=Graph
|
||||
dependency2.to=Kante
|
||||
dependency2.type=UsesDependency
|
||||
dependency3.from=Kante
|
||||
dependency3.to=Knoten
|
||||
dependency3.type=UsesDependency
|
||||
dependency4.from=Kante
|
||||
dependency4.to=GraphElement
|
||||
dependency4.type=UsesDependency
|
||||
dependency5.from=GraphOptions
|
||||
dependency5.to=GraphElement
|
||||
dependency5.type=UsesDependency
|
||||
dependency6.from=Knoten
|
||||
dependency6.to=GraphElement
|
||||
dependency6.type=UsesDependency
|
||||
dependency7.from=Knoten
|
||||
dependency7.to=Kante
|
||||
dependency7.type=UsesDependency
|
||||
dependency8.from=Hilfe
|
||||
dependency8.to=GraphPlotter
|
||||
dependency8.type=UsesDependency
|
||||
dependency9.from=GraphPlotter
|
||||
dependency9.to=Graph
|
||||
dependency9.type=UsesDependency
|
||||
objectbench.height=93
|
||||
objectbench.width=530
|
||||
package.divider.horizontal=0.6
|
||||
package.divider.vertical=0.8204667863554758
|
||||
package.editor.height=450
|
||||
package.editor.width=780
|
||||
package.editor.x=879
|
||||
package.editor.y=186
|
||||
package.frame.height=657
|
||||
package.frame.width=931
|
||||
package.numDependencies=13
|
||||
package.numTargets=7
|
||||
package.showExtends=true
|
||||
package.showUses=true
|
||||
readme.height=58
|
||||
readme.name=@README
|
||||
readme.width=47
|
||||
readme.x=10
|
||||
readme.y=10
|
||||
target1.height=50
|
||||
target1.name=Graph
|
||||
target1.naviview.expanded=true
|
||||
target1.showInterface=false
|
||||
target1.type=ClassTarget
|
||||
target1.width=80
|
||||
target1.x=340
|
||||
target1.y=180
|
||||
target2.height=50
|
||||
target2.name=Kante
|
||||
target2.showInterface=false
|
||||
target2.type=ClassTarget
|
||||
target2.width=80
|
||||
target2.x=240
|
||||
target2.y=260
|
||||
target3.height=50
|
||||
target3.name=GraphElement
|
||||
target3.showInterface=false
|
||||
target3.type=AbstractTarget
|
||||
target3.width=110
|
||||
target3.x=220
|
||||
target3.y=360
|
||||
target4.height=50
|
||||
target4.name=GraphPlotter
|
||||
target4.naviview.expanded=true
|
||||
target4.showInterface=false
|
||||
target4.type=ClassTarget
|
||||
target4.width=110
|
||||
target4.x=410
|
||||
target4.y=80
|
||||
target5.height=50
|
||||
target5.name=GraphOptions
|
||||
target5.showInterface=false
|
||||
target5.type=ClassTarget
|
||||
target5.width=110
|
||||
target5.x=180
|
||||
target5.y=80
|
||||
target6.height=50
|
||||
target6.name=Knoten
|
||||
target6.showInterface=false
|
||||
target6.type=ClassTarget
|
||||
target6.width=80
|
||||
target6.x=460
|
||||
target6.y=260
|
||||
target7.height=50
|
||||
target7.name=Hilfe
|
||||
target7.showInterface=false
|
||||
target7.type=InterfaceTarget
|
||||
target7.width=80
|
||||
target7.x=610
|
||||
target7.y=90
|
||||
Loading…
Add table
Add a link
Reference in a new issue