Browse Source

dummy attribut für knoten im json

Kolja Strohm 7 years ago
parent
commit
0627439ab5

+ 0 - 0
big.graph → big.json


+ 3 - 2
doc/chapter/1introduction.tex

@@ -6,5 +6,6 @@ Thus we develop an application that not only executes this phase, but also prese
 Then each stage of the node placing algorithm by Brandes and Köpf~\cite{brandes_fast_2001} can be executed step by step, either on user input or automatically with a certain delay.
 Then each stage of the node placing algorithm by Brandes and Köpf~\cite{brandes_fast_2001} can be executed step by step, either on user input or automatically with a certain delay.
 After each step the current progress of the algorithm is displayed visually.
 After each step the current progress of the algorithm is displayed visually.
 
 
-In chapter~\ref{ch:architecture} we provide an overview over the \appname 's architecture and chapter~\ref{ch:progress} lists the main features and their progress.
+In chapter~\ref{ch:architecture} we provide an overview over the \appname 's internal architecture while chapter~\ref{ch:ui} presents and explains the graphical user interface.
-\TODO{mention chapter 4?}
+\appname is currently a work in progress so keep in mind that any of the here presented information may be slightly outdated\footnote{even this one}.
+To provide an overview of what is going on, chapter~\ref{ch:progress} lists features and their degree of completion.

+ 82 - 38
doc/chapter/2architecture.tex

@@ -18,10 +18,11 @@ The structure is as follows:
     \item An edge has the attributes that are displayed in table~\ref{table:edge-attributes}.
     \item An edge has the attributes that are displayed in table~\ref{table:edge-attributes}.
 \end{itemize}
 \end{itemize}
 For parsing the JSON file the JSON-java library~\cite{leary_json-java:_2018} is used.
 For parsing the JSON file the JSON-java library~\cite{leary_json-java:_2018} is used.
-
+The classes for reading and writing those JSON files are displayed in figure~\ref{fig:io}.
+The internal representation of graphs is further explained in the section~\ref{sec:model}.
 
 
 \centering
 \centering
-\begin{longtable}{|p{1.8cm}|p{2cm}|p{1.8cm}|p{8.5cm}|}
+\begin{longtable}{|p{1.8cm}|p{2.3cm}|p{1.7cm}|p{8.5cm}|}
     \hline
     \hline
     Attribute & Type & Optional & Explanation \\\hline\hline
     Attribute & Type & Optional & Explanation \\\hline\hline
     name & string & yes & If not omitted, this must be unique for a given parent node. \\\hline
     name & string & yes & If not omitted, this must be unique for a given parent node. \\\hline
@@ -31,10 +32,20 @@ For parsing the JSON file the JSON-java library~\cite{leary_json-java:_2018} is
     The node can be higher if it contains other nodes that need more space. \\\hline
     The node can be higher if it contains other nodes that need more space. \\\hline
     layers & list of lists of nodes & yes & The layers of nodes inside this node (Hierarchy). \\\hline
     layers & list of lists of nodes & yes & The layers of nodes inside this node (Hierarchy). \\\hline
     edges & list of edges & yes & The edges between nodes whose parent node is this node. \\\hline
     edges & list of edges & yes & The edges between nodes whose parent node is this node. \\\hline
-\caption{Node Attributes}
+    \caption{Node Attributes}
-\label{table:node-attributes}
+    \label{table:node-attributes}
 \end{longtable}
 \end{longtable}
 
 
+\begin{figure}[tp]
+    \centering
+    \includegraphics[width=\linewidth, trim={0 20cm 0 0}]{img/IO.pdf}
+    \caption[Class diagram of the \enquote{IO} package]{Class diagram of the \enquote{IO} package, containing utilities for reading and writing graphs.}
+    \label{fig:io}
+\end{figure}
+
+\newpage
+
+\TODO{attribute for dummy nodes}
 \begin{longtable}{|p{1.8cm}|p{2cm}|p{1.8cm}|p{8.5cm}|}
 \begin{longtable}{|p{1.8cm}|p{2cm}|p{1.8cm}|p{8.5cm}|}
     \hline
     \hline
     Attribute & Type & Optional & Explanation \\\hline\hline
     Attribute & Type & Optional & Explanation \\\hline\hline
@@ -42,8 +53,8 @@ For parsing the JSON file the JSON-java library~\cite{leary_json-java:_2018} is
     Must be a node with the same parent node as the node specified by the \enquote{target} attribute. \\\hline
     Must be a node with the same parent node as the node specified by the \enquote{target} attribute. \\\hline
     target & string & no & The name of the target of this edge.
     target & string & no & The name of the target of this edge.
     Must be a node with the same parent node as the node specified by the \enquote{source} attribute. \\\hline
     Must be a node with the same parent node as the node specified by the \enquote{source} attribute. \\\hline
-\caption{Edge Attributes}
+    \caption{Edge Attributes}
-\label{table:edge-attributes}
+    \label{table:edge-attributes}
 \end{longtable}
 \end{longtable}
 \raggedright
 \raggedright
 
 
@@ -54,41 +65,74 @@ For parsing the JSON file the JSON-java library~\cite{leary_json-java:_2018} is
 %    \label{fig:iff}
 %    \label{fig:iff}
 %\end{figure}
 %\end{figure}
 
 
+\TODO{Kante in beispielJSON}
 \begin{figure}
 \begin{figure}
-    \begin{lstlisting}[language=json,emph={}]
+    \begin{lstinputlisting}[language=json,emph={}]{img/graph.json}
-    {
+    \end{lstinputlisting}
-       "layers":[
-          [
-             {
-                "name":"n2",
-                "width":10,
-                "height":10
-             },
-             {
-                "name":"n1",
-                "width":10,
-                "height":10,
-                "layers":[
-                   [
-                      {
-                         "name":"n2",
-                         "width":10,
-                         "height":10
-                      }
-                   ]
-                ]
-             }
-          ]
-       ],
-       "name":"n0"
-    }
-    \end{lstlisting}
     \caption[Example Input File]{Example Input file that is understood by \appname.}
     \caption[Example Input File]{Example Input file that is understood by \appname.}
     \label{fig:json-example}
     \label{fig:json-example}
 \end{figure}
 \end{figure}
 
 
-\section{Internal graph representation}\label{sec:internalGraphRepresentation}
+\section{Internal graph representation, \enquote{Model}}\label{sec:model}
-\TODO{some class diagram}
+One feature that is important to us, is to be able to work with hierarchical graphs (cf.\ chapter~\ref{ch:progress}).
+Therefore a node not only has edges to other nodes, but also it can contain other nodes and edges.
+So far this is similar to what we described in section~\ref{sec:inputFileFormat}.
+Additionally, there are multiple attributes that are used during the computation or as output variables.
+\begin{itemize}
+    \item The attributes \enquote{shift},  \enquote{sink},  \enquote{root} and  \enquote{align} correspond to the variables used by Brandes and Köpf~\cite{brandes_fast_2001}.
+    They are summarized in table~\ref{table:bk-variables}.
+    \item The \enquote{parent} of a node is the node that contains it in the hierarchy.
+    \item The attributes $x$ and $y$ are the coordinates of the node relative to its parent node.
+\end{itemize}
+Similarly, edges have additional attributes:
+\begin{itemize}
+    \item \enquote{dummy} specifies whether they are dummy edges.
+    \item \enquote{conflicted} corresponds to the variable used by Brandes and Köpf~\cite{brandes_fast_2001} and indicates that this edge won't be drawn vertically.
+    \item \enquote{bindPoints} is a list of bend points for the edge, including the beginning and end point of the edge.
+\end{itemize}
+
+A class diagram of the package \enquote{Model} is displayed in figure~\ref{fig:model}.
+
+\begin{figure}[tp]
+    \centering
+    \includegraphics[width=\linewidth, trim={0 6cm 0 0}]{img/Model.pdf}
+    \caption{Class diagram of the \enquote{Model} package.}
+    \label{fig:model}
+\end{figure}
+
+\begin{longtable}{|p{2.8cm}|p{10cm}|}
+    \hline
+    Attribute & Explanation \\\hline\hline
+    root & The root node of the block of this node.
+    Unique for all nodes in the same block. \\\hline
+    sink & The topmost sink in the block graph that can be reached from the block that this node belongs to.
+    Only used for nodes that are the root of a block.
+    Unique for all nodes in the same class. \\\hline
+    shift & The shift of the class that this node belongs to.
+    Only used for nodes that are a sink of a class. \\\hline
+    \caption{Variables also used by Brandes and Köpf~\cite{brandes_fast_2001}}
+    \label{table:bk-variables}
+\end{longtable}
+
+\section{The actual algorithm}\label{sec:theActualAlgorithm}
+This section assumes that the reader is familiar with the node placement algorithm by Brandes and Köpf~\cite{brandes_fast_2001}.
+
+A \enquote{stage} of the algorithm, interface \enquote{AlgorithmStage}, is an interval during which each step of the algorithm is performed in a similar way.
+Each time such a step is performed it returns whether the stage is already finished.
+For example, a forward step in the stage of calculating one extremal layout, class \enquote{ExtremalLayoutCalc}, consists of either a step of calculating the blocks, class \enquote{BlockCalc}, or a step of compacting the layout, class \enquote{Compaction}.
+All the stages are displayed in class diagram~\ref{fig:animated}.
+
+To be able to undo a step each stage needs to implement methods for both forward and backward steps.
+
+\begin{figure}[tp]
+    \centering
+    \includegraphics[width=\linewidth, trim={0 9cm 0 0}]{img/Algorithms_Animated.pdf}
+    \caption{Class diagram of the package \enquote{Algorithms.Animated}.}
+    \label{fig:animated}
+\end{figure}
+
+\section{View}\label{sec:view}
+This section only covers the software architecture regarding the views.
+For an explanation of what is actually displayed, see chapter~\ref{ch:ui}
 
 
-\section{TODO: More Class Diagrams}\label{sec:classDiagrams}
+\TODO{Kolja ausfragen}
-\TODO{maybe even into appendix}

+ 32 - 0
doc/chapter/3ui.tex

@@ -0,0 +1,32 @@
+Note that since the application is still under construction, so not all screenshots may be up to date.
+
+\section{Graphical presentation of the running algorithm}\label{sec:graphicalPresentationOfTheRunningAlgorithm}
+\TODO{under construction}
+\TODO{reference~\ref{fig:animated}}
+\begin{figure}[tp]
+    \centering
+    \includegraphics[width=0.6\linewidth]{img/example.jpg}
+    \caption[A simple graph with 5 nodes]{A simple graph with 5 nodes after the four extremal layout have been computed, but not balanced yet.
+    The vertical directions are down (upper row), up (lower row) and the horizontal directions are left (left column) and right (right column).
+    The background colors of the nodes display which block they belong to: For example the two blue nodes on the top right are in the same block.
+    Round nodes are the roots of the blocks.
+    A colored circle on a node indicates the class that this node belongs to and is also the color of the topmost sink in the block graph.
+    The node that is currently in the focus of the algorithm (whatever this means for the current stage) is highlighted with a grey square (here the node in the rightmost column on the bottom right).
+    Although edges are not drawn during the node placement phase we added them here as straight lines to improve readability.}
+    \label{fig:animated}
+\end{figure}
+
+\section{User interface}\label{sec:userInterface}
+Currently the only way to interact with the application is by keyboard events.
+It is planned to add both additional commands as well as some kind of graphical interface, see chapter~\ref{ch:progress}.
+
+\begin{longtable}{|l|l|}
+    \hline
+    Key & Action \\\hline\hline
+    Left arrow key & Perform one forward step of the algorithm. \\\hline
+    Right arrow key & Perform one backward step (\enquote{undo one step}) of the algorithm. \\\hline
+    P & Pause/unpause the automatic execution. Initially paused. \\\hline
+    D & Print a debug table to standard out. \\\hline
+    \caption{Overview of the currently available keyboard commands.}
+    \label{table:keys}
+\end{longtable}

+ 10 - 4
doc/chapter/3progress.tex → doc/chapter/4progress.tex

@@ -8,7 +8,11 @@ The following features are either planned (\planned), under construction (\progr
     \item[\done] Drawing a graph with specified node sizes and positions.
     \item[\done] Drawing a graph with specified node sizes and positions.
     \item[\progress] Running the node placement algorithm by Brandes and Köpf~\cite{brandes_fast_2001}.
     \item[\progress] Running the node placement algorithm by Brandes and Köpf~\cite{brandes_fast_2001}.
     \begin{itemize}
     \begin{itemize}
-        \item[\done] Calculating the blocks.
+        \item[\progress] Calculating the conflicts between edges.
+        \begin{itemize}
+            \item[\planned] Differentiating between dummy nodes and non-dummy nodes.
+        \end{itemize}
+        \item[\progress] Calculating the blocks.
         \item[\progress] Compacting the layout.
         \item[\progress] Compacting the layout.
         \item[\planned] Combining the layouts.
         \item[\planned] Combining the layouts.
     \end{itemize}
     \end{itemize}
@@ -21,11 +25,13 @@ The following features are either planned (\planned), under construction (\progr
         \item[\progress] Drawing the four extremal layouts and the combined layout separately.
         \item[\progress] Drawing the four extremal layouts and the combined layout separately.
         \item[\planned] Drawing the edges of the block graph (in a different color than other edges).
         \item[\planned] Drawing the edges of the block graph (in a different color than other edges).
     \end{itemize}
     \end{itemize}
-    \item[\done] Running the algorithm step by step manually (by pushing a button labeled \enquote{Step}).
+    \item[\done] Running the algorithm step by step manually.
     \item[\progress] Running the algorithm step by step with configurable delay.
     \item[\progress] Running the algorithm step by step with configurable delay.
     \item[\planned] Using debugger-like commands such as \enquote{step into}, \enquote{step over}, \enquote{step out}.
     \item[\planned] Using debugger-like commands such as \enquote{step into}, \enquote{step over}, \enquote{step out}.
+    \item[\planned] Adding buttons and other graphical elements to support the user interface (low priority).
+    Currently there is only keyboard input (cf.\ section~\ref{sec:userInterface}).
     \item[\done] Working with hierarchical graphs.
     \item[\done] Working with hierarchical graphs.
     \item[\done] Scaling the display with the (adjustable) window size.
     \item[\done] Scaling the display with the (adjustable) window size.
-    \item[\planned] Creating ElkNode~\cite{noauthor_elk:_2018} objects from LayeredNode (\ref{sec:internalGraphRepresentation}) objects
+    \item[\planned] Creating ElkNode~\cite{noauthor_elk:_2018} objects from LayeredNode (\ref{sec:model}) objects
-    \item[\planned] Creating LayeredNode (\ref{sec:internalGraphRepresentation}) objects from ElkNode~\cite{noauthor_elk:_2018} objects (low priority)
+    \item[\planned] Creating LayeredNode (\ref{sec:model}) objects from ElkNode~\cite{noauthor_elk:_2018} objects (low priority)
 \end{itemize}
 \end{itemize}

+ 0 - 0
doc/chapter/4retrospection.tex → doc/chapter/5retrospection.tex


+ 28 - 0
doc/chapter/6contributors.tex

@@ -0,0 +1,28 @@
+\begin{table}[ht]
+	\centering
+    \small
+    \begin{longtable}{p{7cm} p{7cm}}
+        \rowcolor{gray!50}
+		\textbf{Competency} & \textbf{Contributor} \\
+		Producer & Eren Bora Yilmaz \\
+        \rowcolor{gray!25}
+        Producer & Kolja Samuel Strohm \\
+		Lead Designer & Kolja Samuel Strohm \\
+        \rowcolor{gray!25}
+		Documentation & Eren Bora Yilmaz \\
+        Lead Systems Programmer & Kolja Samuel Strohm \\
+        \rowcolor{gray!25}
+		Lead Graphics Programmer & Kolja Samuel Strohm \\
+		Non-German Comments & Eren Bora Yilmaz \\
+        \rowcolor{gray!25}
+		Operations Director & Kolja Samuel Strohm \\
+        Director Of Quality Assurance & Eren Bora Yilmaz \\
+        \rowcolor{gray!25}
+		Senior Community Manager & Eren Bora Yilmaz \\
+        Creative Director & Kolja Samuel Strohm \\
+        \\\\\rowcolor{gray!25}
+		Special Thanks & Jens Burmeister \\\\
+	\end{longtable}
+	\caption{Contributors}
+	\label{table:contributors}
+\end{table}

+ 12 - 7
doc/doc.tex

@@ -84,7 +84,7 @@
 % Quellcode
 % Quellcode
 % für Formatierung in Quelltexten, hier im Anhang
 % für Formatierung in Quelltexten, hier im Anhang
 \usepackage{listings}
 \usepackage{listings}
-\usepackage{color} % Farben
+\usepackage{color, colortbl} % Farben
 
 
 \colorlet{punct}{red!60!black}
 \colorlet{punct}{red!60!black}
 \definecolor{background}{HTML}{EEEEEE}
 \definecolor{background}{HTML}{EEEEEE}
@@ -208,11 +208,12 @@ frame=tb}
         \end{Large}\\
         \end{Large}\\
         \vspace{8mm}
         \vspace{8mm}
         Project documentation\\
         Project documentation\\
-        \vspace{0.4cm}
+        \vspace{2.4 cm}
-        \vspace{2 cm}
         Eren Bora Yilmaz (1036085)\\
         Eren Bora Yilmaz (1036085)\\
         Kolja Samuel Strohm (1036051)\\
         Kolja Samuel Strohm (1036051)\\
         Summer term 2018\\
         Summer term 2018\\
+        \vspace{8mm}
+	    \includegraphics[width=10cm]{img/logo}
     \end{center}
     \end{center}
     \clearpage\null\clearpage
     \clearpage\null\clearpage
 
 
@@ -245,13 +246,17 @@ frame=tb}
     \chapter{Architecture}\label{ch:architecture}
     \chapter{Architecture}\label{ch:architecture}
     \input{chapter/2architecture}
     \input{chapter/2architecture}
 
 
-    \chapter{Current Progress}\label{ch:progress}
+    \chapter{UI and visuals}\label{ch:ui}
-    \input{chapter/3progress}
+    \input{chapter/3ui}
 
 
-    \TODO{UI and visuals chapter}
+    \chapter{Current Progress}\label{ch:progress}
+    \input{chapter/4progress}
 
 
     \chapter{Retrospection}
     \chapter{Retrospection}
-    \input{chapter/4retrospection}
+    \input{chapter/5retrospection}
+
+    \chapter{Contributors}
+    \input{chapter/6contributors}
 
 
     \appendix
     \appendix
     \chapter{Appendix}\label{ch:appendix}
     \chapter{Appendix}\label{ch:appendix}

+ 0 - 0
doc/img/Algorithms.Animated.pdf → doc/img/Algorithms_Animated.pdf


BIN
doc/img/example.jpg


+ 26 - 0
doc/img/graph.json

@@ -0,0 +1,26 @@
+{
+   "layers":[
+      [
+         {
+            "name":"n2",
+            "width":10,
+            "height":10
+         },
+         {
+            "name":"n1",
+            "width":10,
+            "height":10,
+            "layers":[
+               [
+                  {
+                     "name":"n2",
+                     "width":10,
+                     "height":10
+                  }
+               ]
+            ]
+         }
+      ]
+   ],
+   "name":"n0"
+}

BIN
doc/img/logo.jpg


BIN
material/lec07-Nodes-Size.pptx


+ 151 - 0
papergraph.json

@@ -0,0 +1,151 @@
+{
+    "layers": [
+        [
+            {"name":"1"},
+            {"name":"2"}
+        ],
+        [
+            {"name":"d1", "dummy":"true"},
+            {"name":"d2", "dummy":"true"},
+            {"name":"d3", "dummy":"true"},
+            {"name":"3"},
+            {"name":"d4", "dummy":"true"}
+        ],
+        [
+            {"name":"d5", "dummy":"true"},
+            {"name":"d6", "dummy":"true"},
+            {"name":"4"},
+            {"name":"5"},
+            {"name":"d7", "dummy":"true"},
+            {"name":"d8", "dummy":"true"}
+        ],
+        [
+            {"name":"d9", "dummy":"true"},
+            {"name":"d10", "dummy":"true"},
+            {"name":"6"},
+            {"name":"7"},
+            {"name":"d11", "dummy":"true"},
+            {"name":"d12", "dummy":"true"}
+        ],
+        [
+            {"name":"d13", "dummy":"true"},
+            {"name":"d14", "dummy":"true"},
+            {"name":"8"},
+            {"name":"d15", "dummy":"true"},
+            {"name":"d16", "dummy":"true"},
+            {"name":"9"},
+            {"name":"d17", "dummy":"true"},
+            {"name":"d18", "dummy":"true"}
+        ],
+        [
+            {"name":"d19", "dummy":"true"},
+            {"name":"d20", "dummy":"true"},
+            {"name":"10"},
+            {"name":"11"},
+            {"name":"d21", "dummy":"true"},
+            {"name":"d22", "dummy":"true"},
+            {"name":"12"},
+            {"name":"d23", "dummy":"true"},
+            {"name":"d24", "dummy":"true"}
+        ],
+        [
+            {"name":"13"},
+            {"name":"d25", "dummy":"true"},
+            {"name":"14"},
+            {"name":"15"},
+            {"name":"16"},
+            {"name":"d26", "dummy":"true"},
+            {"name":"d27", "dummy":"true"},
+            {"name":"d28", "dummy":"true"},
+            {"name":"d29", "dummy":"true"}
+        ],
+        [
+            {"name":"17"},
+            {"name":"d30", "dummy":"true"},
+            {"name":"18"},
+            {"name":"19"},
+            {"name":"d31", "dummy":"true"},
+            {"name":"20"},
+            {"name":"d32", "dummy":"true"}
+        ],
+        [
+            {"name":"21"},
+            {"name":"22"},
+            {"name":"d33", "dummy":"true"},
+            {"name":"d34", "dummy":"true"}
+        ],
+        [
+            {"name":"23"}
+        ]
+    ],
+    "edges": [
+        {"source":"1","target":"3"},
+        {"source":"1","target":"d1", "dummy":"true"},
+        {"source":"1","target":"d2", "dummy":"true"},
+        {"source":"1","target":"d3", "dummy":"true"},
+        {"source":"2","target":"3"},
+        {"source":"2","target":"d4", "dummy":"true"},
+        {"source":"d1","target":"d5", "dummy":"true"},
+        {"source":"d2","target":"d6", "dummy":"true"},
+        {"source":"d3","target":"4"},
+        {"source":"3","target":"4"},
+        {"source":"3","target":"5"},
+        {"source":"3","target":"d7", "dummy":"true"},
+        {"source":"d4","target":"d8", "dummy":"true"},
+        {"source":"d5","target":"d9", "dummy":"true"},
+        {"source":"d6","target":"d10", "dummy":"true"},
+        {"source":"4","target":"6"},
+        {"source":"5","target":"7"},
+        {"source":"d7","target":"d11", "dummy":"true"},
+        {"source":"d8","target":"d12", "dummy":"true"},
+        {"source":"d9","target":"d13", "dummy":"true"},
+        {"source":"d10","target":"d14", "dummy":"true"},
+        {"source":"6","target":"8"},
+        {"source":"6","target":"d15", "dummy":"true"},
+        {"source":"6","target":"d16", "dummy":"true"},
+        {"source":"7","target":"9"},
+        {"source":"d11","target":"d17", "dummy":"true"},
+        {"source":"d12","target":"d18", "dummy":"true"},
+        {"source":"d13","target":"d19", "dummy":"true"},
+        {"source":"d14","target":"d20", "dummy":"true"},
+        {"source":"8","target":"10"},
+        {"source":"8","target":"11"},
+        {"source":"d15","target":"d21", "dummy":"true"},
+        {"source":"d16","target":"d22", "dummy":"true"},
+        {"source":"9","target":"12"},
+        {"source":"d17","target":"d23", "dummy":"true"},
+        {"source":"d18","target":"d24", "dummy":"true"},
+        {"source":"d19","target":"13"},
+        {"source":"d20","target":"d25", "dummy":"true"},
+        {"source":"10","target":"13"},
+        {"source":"10","target":"14"},
+        {"source":"10","target":"15"},
+        {"source":"11","target":"15"},
+        {"source":"11","target":"16"},
+        {"source":"d21","target":"16"},
+        {"source":"d22","target":"d26", "dummy":"true"},
+        {"source":"12","target":"d27", "dummy":"true"},
+        {"source":"d23","target":"d28", "dummy":"true"},
+        {"source":"d24","target":"d29", "dummy":"true"},
+        {"source":"13","target":"17"},
+        {"source":"14","target":"17"},
+        {"source":"14","target":"18"},
+        {"source":"16","target":"18"},
+        {"source":"16","target":"19"},
+        {"source":"16","target":"20"},
+        {"source":"d25","target":"d30", "dummy":"true"},
+        {"source":"d26","target":"d31", "dummy":"true"},
+        {"source":"d27","target":"20"},
+        {"source":"d28","target":"d32", "dummy":"true"},
+        {"source":"d29","target":"20"},
+        {"source":"18","target":"21"},
+        {"source":"19","target":"22"},
+        {"source":"d30","target":"21"},
+        {"source":"d31","target":"d33", "dummy":"true"},
+        {"source":"21","target":"23"},
+        {"source":"22","target":"23"},
+        {"source":"d32","target":"d34", "dummy":"true"},
+        {"source":"d33","target":"23"},
+        {"source":"d34","target":"23"}
+    ]
+}

+ 0 - 0
save.graph → save.json


+ 5 - 2
save_err1.graph → save_err1.json

@@ -12,11 +12,14 @@
 		],
 		],
 		[
 		[
 			{"name":"6"},
 			{"name":"6"},
-			{"name":"7"}
+			{"name":"7"},
+			{"name":"8"}
 		]
 		]
 	],
 	],
 	"edges":[
 	"edges":[
-		{"source":"0","target":"5"},
+        {"source":"4","target":"6"},
+        {"source":"4","target":"8"},
+        {"source":"0","target":"5"},
 		{"source":"1","target":"5"},
 		{"source":"1","target":"5"},
 		{"source":"2","target":"5"},
 		{"source":"2","target":"5"},
 		{"source":"3","target":"7"},
 		{"source":"3","target":"7"},

+ 12 - 2
src/Algorithms/Animated/BK/BKNodePlacement.java

@@ -18,6 +18,7 @@ public class BKNodePlacement extends AnimatedAlgorithm {
 	
 	
 	private enum State
 	private enum State
 	{
 	{
+		CONFLICTS,
 		LAYOUT1,
 		LAYOUT1,
 		LAYOUT2,
 		LAYOUT2,
 		LAYOUT3,
 		LAYOUT3,
@@ -25,13 +26,15 @@ public class BKNodePlacement extends AnimatedAlgorithm {
 		COMBINE
 		COMBINE
 	}
 	}
 	
 	
+	private ConflictDetection conftion;
 	private State state;
 	private State state;
 	private ExtremalLayoutCalc layouts[];
 	private ExtremalLayoutCalc layouts[];
 	private Combine combine;
 	private Combine combine;
 	
 	
 	public BKNodePlacement(AnimationController controller, LayeredGraphNode graph) {
 	public BKNodePlacement(AnimationController controller, LayeredGraphNode graph) {
 		super(controller, graph);
 		super(controller, graph);
-		state = State.LAYOUT1;
+		state = State.CONFLICTS;
+		conftion = new ConflictDetection( graph );
 		layouts = new ExtremalLayoutCalc[ 4 ];
 		layouts = new ExtremalLayoutCalc[ 4 ];
 		layouts[ 0 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_LEFT, graph );
 		layouts[ 0 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_LEFT, graph );
 		layouts[ 1 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_RIGHT, graph );
 		layouts[ 1 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_RIGHT, graph );
@@ -44,6 +47,10 @@ public class BKNodePlacement extends AnimatedAlgorithm {
 	public StageStatus forwardStep() {
 	public StageStatus forwardStep() {
 		switch( state )
 		switch( state )
 		{
 		{
+		case CONFLICTS:
+			if( conftion.forwardStep() == StageStatus.FINISHED )
+				state = State.LAYOUT1;
+			break;
 		case LAYOUT1:
 		case LAYOUT1:
 			if( layouts[ 0 ].forwardStep() == AlgorithmStage.StageStatus.FINISHED )
 			if( layouts[ 0 ].forwardStep() == AlgorithmStage.StageStatus.FINISHED )
 				state = State.LAYOUT2;
 				state = State.LAYOUT2;
@@ -70,8 +77,11 @@ public class BKNodePlacement extends AnimatedAlgorithm {
 	public StageStatus backwardStep() {
 	public StageStatus backwardStep() {
 		switch( state )
 		switch( state )
 		{
 		{
+		case CONFLICTS:
+			return conftion.backwardStep();
 		case LAYOUT1:
 		case LAYOUT1:
-			return layouts[ 0 ].backwardStep();
+			if( layouts[ 0 ].backwardStep() == StageStatus.FINISHED )
+				state = State.CONFLICTS;
 		case LAYOUT2:
 		case LAYOUT2:
 			if( layouts[ 1 ].backwardStep() == AlgorithmStage.StageStatus.FINISHED )
 			if( layouts[ 1 ].backwardStep() == AlgorithmStage.StageStatus.FINISHED )
 				state = State.LAYOUT1;
 				state = State.LAYOUT1;

+ 20 - 11
src/Algorithms/Animated/BK/BlockCalc.java

@@ -2,6 +2,7 @@ package Algorithms.Animated.BK;
 
 
 import java.awt.Color;
 import java.awt.Color;
 import java.util.ArrayList;
 import java.util.ArrayList;
+import java.util.Collections;
 
 
 import Algorithms.Animated.AlgorithmStage;
 import Algorithms.Animated.AlgorithmStage;
 import Algorithms.Animated.BackwardAction;
 import Algorithms.Animated.BackwardAction;
@@ -21,7 +22,7 @@ public class BlockCalc implements AlgorithmStage {
 	private int r;
 	private int r;
 	private LayeredGraphNode graph;
 	private LayeredGraphNode graph;
 	private ArrayList< ArrayList< ExtremalLayoutCalc > > subgraphAlgs;
 	private ArrayList< ArrayList< ExtremalLayoutCalc > > subgraphAlgs;
-	private ArrayList< BackwardAction > backwards;
+	private ArrayList< BackwardAction > backwards; // TODO: evtl richtigen "Stack" benutzen
 	private LayoutType layout;
 	private LayoutType layout;
 	int step;
 	int step;
 	
 	
@@ -64,12 +65,21 @@ public class BlockCalc implements AlgorithmStage {
 	
 	
 	private int calcNodeIndex( int index )
 	private int calcNodeIndex( int index )
 	{
 	{
-        if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
+        if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.BOTTOM_TOP_LEFT )
             return index;
             return index;
-        //if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
+        if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-        //    return graph.getContainedLayers().get( calcLayerIndex() ).size() - index - 1;
+            return graph.getContainedLayers().get( calcLayerIndex() ).size() - index - 1;
         return index;
         return index;
 	}
 	}
+    
+    private int calcBeforeLayerNodeIndex( int index )
+    {
+        if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.BOTTOM_TOP_LEFT )
+            return index;
+        if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
+            return graph.getContainedLayers().get( calcBeforeLayerIndex() ).size() - index - 1;
+        return index;
+    }
 	
 	
 	@Override
 	@Override
 	public StageStatus forwardStep() {
 	public StageStatus forwardStep() {
@@ -87,6 +97,8 @@ public class BlockCalc implements AlgorithmStage {
             incommingEdges = current.getSortedIncomingEdges();
             incommingEdges = current.getSortedIncomingEdges();
         if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
         if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
             incommingEdges = current.getSortedOutgoingEdges();
             incommingEdges = current.getSortedOutgoingEdges();
+        if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
+        Collections.reverse( incommingEdges );
 		if( incommingEdges.size() == 0 )
 		if( incommingEdges.size() == 0 )
 		{
 		{
 			backwards.add( 0, () -> {
 			backwards.add( 0, () -> {
@@ -94,11 +106,7 @@ public class BlockCalc implements AlgorithmStage {
 			});
 			});
 			return calcNextState();
 			return calcNextState();
 		}
 		}
-		int[] ms = null;
+		int[] ms = {(incommingEdges.size() + 1) / 2, (int)( (incommingEdges.size() + 1) / 2.0 + 0.5 )};
-		if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.BOTTOM_TOP_LEFT )
-		    ms = new int[]{(incommingEdges.size() + 1) / 2, (int)( (incommingEdges.size() + 1) / 2.0 + 0.5 )};
-        if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-            ms = new int[]{(int)( (incommingEdges.size() + 1) / 2.0 + 0.5 ), (incommingEdges.size() + 1) / 2};
 		boolean backwardsAdded = false;
 		boolean backwardsAdded = false;
 		for( int m : ms )
 		for( int m : ms )
 		{
 		{
@@ -110,7 +118,8 @@ public class BlockCalc implements AlgorithmStage {
                 if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
                 if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
                     u = incommingEdges.get( m - 1 ).getTargets().get( 0 );
                     u = incommingEdges.get( m - 1 ).getTargets().get( 0 );
                 ArrayList<LayeredGraphEdge> conflicts = incommingEdges.get( m - 1 ).calcConflictedEdges();
                 ArrayList<LayeredGraphEdge> conflicts = incommingEdges.get( m - 1 ).calcConflictedEdges();
-		        if( !incommingEdges.get( m - 1 ).isConflicted( layout ) && calcNodeIndex( r ) < calcNodeIndex( graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) + 1 ) )
+                
+		        if( !incommingEdges.get( m - 1 ).isConflicted( layout ) && r < calcBeforeLayerNodeIndex( graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) ) + 1 )
 		        {
 		        {
 		        	System.out.println( "" );
 		        	System.out.println( "" );
 		        	ArrayList< Boolean > oldConflicts = new ArrayList<>();
 		        	ArrayList< Boolean > oldConflicts = new ArrayList<>();
@@ -128,7 +137,7 @@ public class BlockCalc implements AlgorithmStage {
 		            current.setColor( u.getRoot( layout ).getColor( layout ), layout );
 		            current.setColor( u.getRoot( layout ).getColor( layout ), layout );
 		            current.setRoot( u.getRoot( layout ), layout );
 		            current.setRoot( u.getRoot( layout ), layout );
 		            current.setAlignTo( current.getRoot( layout ), layout );
 		            current.setAlignTo( current.getRoot( layout ), layout );
-		            r = graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) + 1;
+		            r = calcBeforeLayerNodeIndex( graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) ) + 1;
 		            int oldStep = step++;
 		            int oldStep = step++;
 		            final LayeredGraphNode uf = u;
 		            final LayeredGraphNode uf = u;
 		            backwards.add( 0, () -> {
 		            backwards.add( 0, () -> {

+ 11 - 19
src/Algorithms/Animated/BK/Compaction.java

@@ -1,7 +1,6 @@
 package Algorithms.Animated.BK;
 package Algorithms.Animated.BK;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
-import java.util.Collections;
 
 
 import Algorithms.Animated.AlgorithmStage;
 import Algorithms.Animated.AlgorithmStage;
 import Algorithms.Animated.BackwardAction;
 import Algorithms.Animated.BackwardAction;
@@ -55,13 +54,9 @@ public class Compaction implements AlgorithmStage{
 		return max;
 		return max;
 	}
 	}
 	
 	
-	@SuppressWarnings("unchecked")
 	private LayeredGraphNode getNodeFromIndex( int index )
 	private LayeredGraphNode getNodeFromIndex( int index )
 	{
 	{
-		ArrayList< ArrayList< LayeredGraphNode > > layers = (ArrayList<ArrayList<LayeredGraphNode>>) graph.getContainedLayers().clone();
+	    for( ArrayList< LayeredGraphNode > l : graph.getContainedLayers() )
-        if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
-        	Collections.reverse( layers );
-	    for( ArrayList< LayeredGraphNode > l : layers )
 	    {
 	    {
 	        if( index >= l.size() )
 	        if( index >= l.size() )
 	            index -= l.size();
 	            index -= l.size();
@@ -87,7 +82,7 @@ public class Compaction implements AlgorithmStage{
 				{
 				{
 					if( getNodeFromIndex( vIndex ).isXUndefined( layout ) && getNodeFromIndex( vIndex ) == getNodeFromIndex( vIndex ).getRoot( layout ) )
 					if( getNodeFromIndex( vIndex ).isXUndefined( layout ) && getNodeFromIndex( vIndex ) == getNodeFromIndex( vIndex ).getRoot( layout ) )
 					{
 					{
-						found = true;
+	                    found = true;
 						break;
 						break;
 					}
 					}
 				}
 				}
@@ -111,7 +106,7 @@ public class Compaction implements AlgorithmStage{
 					f.v.setX( 0, true, layout );
 					f.v.setX( 0, true, layout );
 					f.v.setSelected( layout ); // zeige knoten als aktiven knoten an
 					f.v.setSelected( layout ); // zeige knoten als aktiven knoten an
 					f.w = f.v;
 					f.w = f.v;
-                    System.out.println( "call place_block( " + f.v.getName() + " )" );
+                    System.out.println( "call place_block( " + f.v + " )" );
 					stack.add( 0, f );
 					stack.add( 0, f );
 					
 					
 					// die "undo"-action
 					// die "undo"-action
@@ -143,7 +138,7 @@ public class Compaction implements AlgorithmStage{
 							nsf.v.setX( 0, true, layout );
 							nsf.v.setX( 0, true, layout );
 							nsf.v.setSelected( layout ); // zeige knoten als aktiven knoten an
 							nsf.v.setSelected( layout ); // zeige knoten als aktiven knoten an
 							nsf.w = nsf.v;
 							nsf.w = nsf.v;
-		                    System.out.println( "call place_block( " + nsf.v.getName() + " )" );
+		                    System.out.println( "call place_block( " + nsf.v + " )" );
 							stack.add( 0, nsf );
 							stack.add( 0, nsf );
 		                    
 		                    
 		                    // die "undo"-action
 		                    // die "undo"-action
@@ -170,7 +165,7 @@ public class Compaction implements AlgorithmStage{
 						sf.w.setSelected( layout );
 						sf.w.setSelected( layout );
 						if( sf.w == sf.v ) // schleifenabbruchbedingung
 						if( sf.w == sf.v ) // schleifenabbruchbedingung
 						{ //abbrechen, placeblock beendet
 						{ //abbrechen, placeblock beendet
-                            System.out.println( "return place_block( " + sf.v.getName() + " )" );
+                            System.out.println( "return place_block( " + sf.v + " )" );
 							stack.remove( 0 );
 							stack.remove( 0 );
 							actions.add( 0, ()-> {
 							actions.add( 0, ()-> {
 								stack.add( 0, sf );
 								stack.add( 0, sf );
@@ -187,7 +182,7 @@ public class Compaction implements AlgorithmStage{
 						}
 						}
 					}	
 					}	
 				}
 				}
-				else // der Teil nach "placeBlock(u)", genannt "absolute coordinates"
+				else // ein "placeBlock(u)" aufruf hat gerade returned
 				{
 				{
 				    // alte Werte merken für undo
 				    // alte Werte merken für undo
 					LayeredGraphNode oldSink = sf.v.getSink( layout );	
 					LayeredGraphNode oldSink = sf.v.getSink( layout );	
@@ -203,13 +198,9 @@ public class Compaction implements AlgorithmStage{
                         sf.v.setSink( sf.u.getSink( layout ), layout ); // sink[v] := sink[u]
                         sf.v.setSink( sf.u.getSink( layout ), layout ); // sink[v] := sink[u]
 
 
 					if( sf.v.getSink( layout ) != sf.u.getSink( layout ) ) // sink[v] != sink [u]?
 					if( sf.v.getSink( layout ) != sf.u.getSink( layout ) ) // sink[v] != sink [u]?
-					{
 						sf.u.getSink( layout ).setShift( // shift[sink[u]] =
 						sf.u.getSink( layout ).setShift( // shift[sink[u]] =
 						  Math.min( sf.u.getSink( layout ).getShift( layout ),  // min(shift[sink[u]]
 						  Math.min( sf.u.getSink( layout ).getShift( layout ),  // min(shift[sink[u]]
 						          sf.v.getX( layout ) - sf.u.getX( layout ) - calcSpacing() ), layout ); // y_v - y_u - s
 						          sf.v.getX( layout ) - sf.u.getX( layout ) - calcSpacing() ), layout ); // y_v - y_u - s
-						System.out.println( "Set Shift von " + sf.u.getSink( layout ).getName() + " to " + Math.min( sf.u.getSink( layout ).getShift( layout ),  // min(shift[sink[u]]
-						          sf.v.getX( layout ) - sf.u.getX( layout ) - calcSpacing() ) );
-					}
 					else
 					else
 					    // y_v = max {y_v, y_u + s}
 					    // y_v = max {y_v, y_u + s}
 						sf.v.setX( Math.max( sf.v.getX( layout ), sf.u.getX( layout ) + calcSpacing() ), true, layout );
 						sf.v.setX( Math.max( sf.v.getX( layout ), sf.u.getX( layout ) + calcSpacing() ), true, layout );
@@ -224,7 +215,7 @@ public class Compaction implements AlgorithmStage{
 					
 					
 					if( sf.w == sf.v ) // schleifenabbruchbedingung
 					if( sf.w == sf.v ) // schleifenabbruchbedingung
 					{ //abbrechen, placeblock beendet  
 					{ //abbrechen, placeblock beendet  
-					    System.out.println( "return place_block( " + sf.v.getName() + " )" );
+					    System.out.println( "return place_block( " + sf.v + " )" );
 						stack.remove( 0 );
 						stack.remove( 0 );
 						actions.add( 0, ()-> {
 						actions.add( 0, ()-> {
 							stack.add( 0, sf );
 							stack.add( 0, sf );
@@ -250,13 +241,14 @@ public class Compaction implements AlgorithmStage{
 				}
 				}
 			}
 			}
 		}
 		}
-		else if( state == CompactionState.APPLY_SHIFT )
+		else if( state == CompactionState.APPLY_SHIFT )// "Compute absolute coordinates"
 		{
 		{
-			LayeredGraphNode v = getNodeFromIndex( vIndex );
+			LayeredGraphNode v = graph.getContainedNodes().get( vIndex );
 			double oldX = v.getX( layout );
 			double oldX = v.getX( layout );
 			boolean oldDef = !v.isXUndefined( layout );
 			boolean oldDef = !v.isXUndefined( layout );
+			
 			v.setSelected( layout );
 			v.setSelected( layout );
-			v.setX( v.getRoot( layout ).getX( layout ), true, layout );
+			v.setX( v.getRoot( layout ).getX( layout ), true, layout ); // y_v = y_root[v]
 			if( v == v.getRoot( layout ) && v.getSink( layout ).getShift( layout ) < Double.POSITIVE_INFINITY )
 			if( v == v.getRoot( layout ) && v.getSink( layout ).getShift( layout ) < Double.POSITIVE_INFINITY )
 				v.setX( v.getX( layout ) + v.getSink( layout ).getShift( layout ), true, layout );
 				v.setX( v.getX( layout ) + v.getSink( layout ).getShift( layout ), true, layout );
 			actions.add( 0, ()-> {
 			actions.add( 0, ()-> {

+ 95 - 0
src/Algorithms/Animated/BK/ConflictDetection.java

@@ -0,0 +1,95 @@
+package Algorithms.Animated.BK;
+
+import java.util.ArrayList;
+
+import Algorithms.Animated.AlgorithmStage;
+import Algorithms.Animated.BackwardAction;
+import Model.LayeredGraphEdge;
+import Model.LayeredGraphNode;
+
+public class ConflictDetection implements AlgorithmStage {
+
+    private LayeredGraphNode graph;
+    private ArrayList< BackwardAction > actions;
+    
+    private int i;
+    private int l1;
+    
+    ConflictDetection( LayeredGraphNode graph )
+    {
+        this.graph = graph;
+        actions = new ArrayList<>();
+        i = 1;
+        l1 = 0;
+    }
+    
+    @Override
+    public StageStatus forwardStep() {
+    	int oldI = i;
+    	int oldL1 = l1;
+    	LayeredGraphNode curr = graph.getContainedLayers().get( i + 1 ).get( l1 );
+    	curr.setSelected( null );
+    	ArrayList< LayeredGraphEdge > edges = curr.getIncomingEdges();
+    	LayeredGraphEdge dummyEdge = null;
+    	for( LayeredGraphEdge e : edges )
+    	{
+    		if( e.isDummyEdge() )
+    		{
+    			dummyEdge = e;
+    			break;
+    		}
+    	}
+    	ArrayList< LayeredGraphEdge > conflicts = new ArrayList<>();
+        if( dummyEdge != null )
+        {
+    		for( LayeredGraphEdge e : edges )
+    		{
+    			if( e.isDummyEdge() )
+    			{
+    				ArrayList< LayeredGraphEdge > conf = e.calcConflictedEdges();
+    				for( LayeredGraphEdge ce : conf )
+    				{
+    					if( !ce.isDummyEdge() )
+    						conflicts.add( ce );
+    				}
+    			}
+    		}
+        }
+        for( LayeredGraphEdge c : conflicts )
+        	c.setConflicted( true, null );
+    	StageStatus status =  calcNextStatus();
+    	actions.add( ()->{
+    		i = oldI;
+    		l1 = oldL1;
+            for( LayeredGraphEdge c : conflicts )
+            	c.setConflicted( false, null );
+    	});
+    	return status;
+    }
+    
+    private StageStatus calcNextStatus()
+    {
+        l1++;
+        if( l1 >= graph.getContainedLayers().get( i + 1 ).size() )
+        {
+            i++;
+            if( i >= graph.getContainedLayers().size() - 2 )
+            {
+                i--;
+                l1--;
+                return StageStatus.FINISHED;
+            }
+            l1 = 0;
+        }
+        return StageStatus.UNFINISHED;
+    }
+
+    @Override
+    public StageStatus backwardStep() {
+        if( actions.size() == 0 )
+        	return StageStatus.FINISHED;
+        actions.get( 0 ).reverse();
+        actions.remove( 0 );
+        return StageStatus.UNFINISHED;
+    }
+}

+ 8 - 1
src/IO/Reader.java

@@ -57,6 +57,10 @@ public class Reader {
 		LayeredGraphNode newNode = new LayeredNode( null, null );
 		LayeredGraphNode newNode = new LayeredNode( null, null );
 		if( parent != null )
 		if( parent != null )
 			newNode = parent.createNode( null );
 			newNode = parent.createNode( null );
+		if( node.has( "dummy" ) && node.getBoolean( "dummy" ) )
+		{
+			newNode.setDummyNode( true );
+		}
         if( node.has( "name" ) )
         if( node.has( "name" ) )
         {
         {
             if( parent != null && parent.findNodeByName( node.getString( "name" ) ) != null )
             if( parent != null && parent.findNodeByName( node.getString( "name" ) ) != null )
@@ -96,7 +100,10 @@ public class Reader {
             throw new JSONException( edge + " is no valid Layered Graph Edge." );
             throw new JSONException( edge + " is no valid Layered Graph Edge." );
         if( parent.findNodeByName( edge.getString( "target" ) ) == null )
         if( parent.findNodeByName( edge.getString( "target" ) ) == null )
             throw new JSONException( edge + " is no valid Layered Graph Edge." );
             throw new JSONException( edge + " is no valid Layered Graph Edge." );
-		return parent.createSimpleEdge( null, parent.findNodeByName( edge.getString( "source" ) ), parent.findNodeByName( edge.getString( "target" ) ) );
+        LayeredGraphEdge newEdge = parent.createSimpleEdge( null, parent.findNodeByName( edge.getString( "source" ) ), parent.findNodeByName( edge.getString( "target" ) ) );
+        if( parent.findNodeByName( edge.getString( "source" ) ).isDummyNode() && parent.findNodeByName( edge.getString( "target" ) ).isDummyNode() )
+        	newEdge.setDummyEdge();
+		return newEdge;
 	}
 	}
 	
 	
 	private ArrayList<LayeredGraphNode> parseLayer( JSONArray layer, LayeredGraphNode parent ) throws JSONException
 	private ArrayList<LayeredGraphNode> parseLayer( JSONArray layer, LayeredGraphNode parent ) throws JSONException

+ 2 - 0
src/IO/Writer.java

@@ -64,6 +64,8 @@ public class Writer {
         }
         }
         node.put( "edges", edges );
         node.put( "edges", edges );
         node.put( "name", graph.getName() );
         node.put( "name", graph.getName() );
+        if( graph.isDummyNode() )
+        	node.put( "dummy", "true" );
         return node;
         return node;
     }
     }
     
     

+ 1 - 1
src/Main.java

@@ -13,7 +13,7 @@ import View.MainView;
 public class Main {
 public class Main {
 
 
 	public static void main(String[] args) {
 	public static void main(String[] args) {
-		Reader r = new Reader( "save_err1.graph" );
+		Reader r = new Reader( "papergraph.json" );
 		LayeredGraphNode graph = r.readInputGraph();
 		LayeredGraphNode graph = r.readInputGraph();
 	    //RandomGraphGenerator r = new RandomGraphGenerator( 0.1, 0.2, 5,5, 5, 5, 1 );
 	    //RandomGraphGenerator r = new RandomGraphGenerator( 0.1, 0.2, 5,5, 5, 5, 1 );
 	    //LayeredGraphNode graph = r.createRandomNode( null, 0 );
 	    //LayeredGraphNode graph = r.createRandomNode( null, 0 );

+ 2 - 0
src/Model/LayeredGraphNode.java

@@ -39,6 +39,8 @@ public interface LayeredGraphNode {
     public void update();
     public void update();
     public void setSelected( LayoutType layoutType );
     public void setSelected( LayoutType layoutType );
     public boolean isSelected( LayoutType layout );
     public boolean isSelected( LayoutType layout );
+    public void setDummyNode( boolean dummy );
+    public boolean isDummyNode();
     
     
     /**
     /**
      * Setzt den Index des Layers, zu dem der Knoten geh�ren soll
      * Setzt den Index des Layers, zu dem der Knoten geh�ren soll

+ 14 - 0
src/Model/LayeredNode.java

@@ -23,6 +23,7 @@ public class LayeredNode implements LayeredGraphNode {
     // for this node
     // for this node
     private ElkNode original;
     private ElkNode original;
     private LayeredGraphNode parent;
     private LayeredGraphNode parent;
+    private boolean dummy;
     
     
     private class LayoutInfo
     private class LayoutInfo
     {
     {
@@ -76,6 +77,19 @@ public class LayeredNode implements LayeredGraphNode {
             l.shift = Double.POSITIVE_INFINITY;
             l.shift = Double.POSITIVE_INFINITY;
             l.xUndef = true;
             l.xUndef = true;
         }
         }
+        dummy = false;
+    }
+    
+    @Override
+    public void setDummyNode( boolean dummy )
+    {
+    	this.dummy = dummy;
+    }
+    
+    @Override
+    public boolean isDummyNode()
+    {
+    	return dummy;
     }
     }
 
 
     @Override
     @Override

+ 2 - 0
src/View/EdgeView.java

@@ -89,6 +89,8 @@ public class EdgeView extends JPanel {
         ((Graphics2D)g).setStroke(new BasicStroke(1));
         ((Graphics2D)g).setStroke(new BasicStroke(1));
         //System.out.println( "Clipping: x:" + g.getClip().getBounds().getX() + " y:" + g.getClip().getBounds().getY() + " w:" + g.getClip().getBounds().getWidth() + " h:" + g.getClip().getBounds().getHeight() );
         //System.out.println( "Clipping: x:" + g.getClip().getBounds().getX() + " y:" + g.getClip().getBounds().getY() + " w:" + g.getClip().getBounds().getWidth() + " h:" + g.getClip().getBounds().getHeight() );
         g.setColor( Color.GREEN );
         g.setColor( Color.GREEN );
+        if( model.isConflicted( layout ) )
+        	g.setColor( Color.RED );
         ArrayList<Point> bps = model.getLinePoints( layout );
         ArrayList<Point> bps = model.getLinePoints( layout );
         for( int i = 1; i < bps.size(); i++ )
         for( int i = 1; i < bps.size(); i++ )
         {
         {

+ 1 - 1
src/View/MainView.java

@@ -63,7 +63,7 @@ public class MainView {
             public void keyPressed(KeyEvent e) {
             public void keyPressed(KeyEvent e) {
                 if( e.getKeyCode() == KeyEvent.VK_S )
                 if( e.getKeyCode() == KeyEvent.VK_S )
                 {
                 {
-                    Writer w = new Writer( "save.graph" );
+                    Writer w = new Writer( "save.json" );
                     w.writeOutputGraph( graph );
                     w.writeOutputGraph( graph );
                 }
                 }
                 if( e.getKeyCode() == KeyEvent.VK_LEFT )
                 if( e.getKeyCode() == KeyEvent.VK_LEFT )

+ 4 - 3
src/View/NodeView.java

@@ -84,12 +84,13 @@ public class NodeView extends JPanel {
 			g.fillRect( 0, 0, (int)model.getWidth( layout )-1, (int)model.getHeight( layout )-1 );
 			g.fillRect( 0, 0, (int)model.getWidth( layout )-1, (int)model.getHeight( layout )-1 );
 		}
 		}
 		Border linebor = BorderFactory.createLineBorder(model.getColor( layout ), 5);
 		Border linebor = BorderFactory.createLineBorder(model.getColor( layout ), 5);
-		if( model.getRoot( layout ) != model )
+		if( model.getRoot( layout ) != model || model.getContainedNodes().size() != 0  )
 			linebor.paintBorder( this, g2, 0, 0, (int)model.getWidth( layout )-1, (int)model.getHeight( layout )-1 );
 			linebor.paintBorder( this, g2, 0, 0, (int)model.getWidth( layout )-1, (int)model.getHeight( layout )-1 );
-		if( model.getRoot( layout ).getSink( layout ).getColor( layout ) != model.getColor( layout ) )
+		if( model.getRoot( layout ).getSink( layout ).getColor( layout ) != model.getColor( layout ))
 		{
 		{
     		g.setColor( model.getRoot( layout ).getSink( layout ).getColor( layout ) );
     		g.setColor( model.getRoot( layout ).getSink( layout ).getColor( layout ) );
-    		g.fillOval( (int)model.getWidth( layout ) / 2 - (int)model.getWidth( layout ) / 3, (int)model.getHeight( layout ) / 2 - (int)model.getHeight( layout ) / 3, (int)model.getWidth( layout ) / 3 * 2, (int)model.getHeight( layout ) / 3 * 2 );
+    		if( model.getContainedNodes().size() == 0 )
+    		    g.fillOval( (int)model.getWidth( layout ) / 2 - (int)model.getWidth( layout ) / 3, (int)model.getHeight( layout ) / 2 - (int)model.getHeight( layout ) / 3, (int)model.getWidth( layout ) / 3 * 2, (int)model.getHeight( layout ) / 3 * 2 );
 		}
 		}
 	}
 	}
 }
 }

+ 0 - 0
test.graph → test.json


+ 0 - 0
test2.graph → test2.json


+ 0 - 0
test3.graph → test3.json


+ 0 - 0
test4.graph → test4.json