1

I have 7 classes and wanted to make a UML-diagram of these in latex. I did manage to code it but take a look at the result (I did even try to rescale and rearrange): enter image description here You can't even identify all the lines showing the relationships. The UML is very messy as you can see so I would like to know if it is possible to make this UML in Latex such that it looks more clean? Code:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{fullpage}
\usepackage[schoo,simplified]{pgf-umlcd}
\date{January 2019}

\begin{document}



\maketitle

\section{UML-diagram (se næste side)}
\newpage
\begin{tikzpicture}
\begin{package}{Chess}
\begin{class}[text width = 5cm]{chessPiece}{0,0}
    \attribute{\textit{nameOfType : string}}
    \attribute{color : Color}
    \attribute{position : Position option with get/set = None}
    \attribute{\textit{candidateRelativeMoves : Position list list}}
    \attribute{}
    \operation{}
    \operation{ToString : unit $\rightarrow$ string}
    \operation{availableMoves : Board $\rightarrow$ Position list}
    \operation{isThreatened : Board : chessPiece : Position $\rightarrow$ bool}
    \operation{}
\end{class}
\begin{class}[text width = 5cm]{Board}{-5.5,0}
    \attribute{Item : : chessPiece option with set}
    \operation{static validPositionWrap : Position $\rightarrow$ Position option}
    \operation{ToString : unit $\rightarrow$ string}
    \operation{move : Position : Position $\rightarrow$ unit}
    \operation{getVacantNOccupied : chessPiece : Position list $\rightarrow$ unit}
    \operation{getVacantNNeighbours : chessPiece : Position list $\rightarrow$ unit}
\end{class}
\end{package}
\begin{package}{Pieces}
\begin{class}[text width = 3cm]{king}{-11,-1}
\inherit{chessPiece}
\attribute{nameOfType : string= "king"}
\attribute{candidateRelativeMoves = [[(-1,0)];[(-1,1)];[(0,1)];[(1,1)];
      [(1,0)];[(1,-1)];[(0,-1)];[(-1,-1)]]}
\end{class}
\begin{class}[text width = 3cm]{rook}{-11,-5}
    \inherit{chessPiece}
    \attribute{nameOfType : string= "rook"}
    \attribute{candidateRelativeMoves = List.map (swap List.map [1..7]) indToRel}
\end{class}
\end{package}
\begin{package}{Interactives}
\begin{class}[text width = 5cm]{Player}{0,-8}
    \attribute{pieceToMove : chessPiece option = None}
    \operation{nextMove : Board $\rightarrow$ string}
\end{class}
\begin{class}[text width = 5 cm]{Human}{0, -11}
    \inherit{Player}
\end{class}
\end{package}
\begin{class}[text width = 5cm]{Game}{-8,-10}
    \attribute{player1 : Human}
    \attribute{player2 : Human}
    \attribute{\_board : Board}
    \operation{setup : unit}
    \operation{run : unit}
    \operation{valid : string [] $\rightarrow$ Human $\rightarrow$ bool}
\end{class}
\unidirectionalAssociation {chessPiece}{}{}{Board}
\unidirectionalAssociation{Game}{}{}{chessPiece}
\unidirectionalAssociation{Game}{}{}{Player}
\composition{Game}{}{}{king}
\composition{Game}{}{}{rook}
\composition{Game}{}{}{Human}
\composition{Game}{}{}{Board}
\composition{Player}{}{}{chessPiece}
\end{tikzpicture}
\end{document}

Example of a way better version, with example of a modified arrow: enter image description here

  • 3
    Welcome to TeX.SE. It would be helpful if you composed a fully compilable minimal working example (MWE) including \documentclass and the appropriate packages that sets up the problem. While solving problems can be fun, setting them up is not. Then, those trying to help can simply cut and paste your MWE and get started on solving the problem. – user36296 Jan 18 at 12:24
  • 1
    Welcome to the site! In addition to providing a MWE, you should ask a specific question. For example, do you want the pieces of the diagram to be spaced out more? Do you want the arrowheads to be larger? etc. You might also want to include an image of a UML diagram (maybe from the web somewhere) that you think looks good. – James Jan 18 at 12:26
  • @James Well, I do not care how it is done, I just want the UML to be understandable and not messy as the one I showed. – npp Jan 18 at 13:30
  • @samcarter The post has been edited with the code to compile it. Thanks for the tip :) Hope you or someone else can help now. – npp Jan 18 at 13:32
  • @npp Unfortunately your code does not compile because things like \end{document} are missing. – user36296 Jan 18 at 13:34
2

How does this look? Mostly I just repositioned things a bit, changed some text widths and the font size. Note I positioned some of the classes relative to other classes (see Is there any method to create UML using LaTeX without giving (x,y) co-ordinate? for more about that), which makes aligning things easier.

If you have suggestions for modifications, feel free to add them in comments. For example, it would certainly be possible to draw the various arrows differently, they need not be straight lines, but it might require some more manual work, rather than pgf-umlcds macro (\composition etc.).

The code below show a few methods for making the inherit-arrow between king and chessPiece go around the Chess package. This is done "manually", using a standard TikZ \draw macro.

They mostly make use of defining named coordinates at the corner points of the path, and using -|/|- path specifications (see TikZ: What EXACTLY does the the |- notation for arrows do?) to draw the line. To get the correct look, I add the umlcd style inherit line style. Some of the methods require specific TikZ libraries, mentioned in comments.

enter image description here

\documentclass{article}
\usepackage[school,simplified]{pgf-umlcd}
\usetikzlibrary{calc}
\usetikzlibrary{positioning}
\usepackage{fullpage}

\begin{document}   
\begin{tikzpicture}[font=\footnotesize] % reduce fontsize
\begin{package}{Chess}
\begin{class}[text width = 3.3cm]{chessPiece}{0,0}
    \attribute{\textit{nameOfType : string}}
    \attribute{color : Color}
    \attribute{position : Position option with get/set = None}
    \attribute{\textit{candidateRelativeMoves : Position list list}}
    \attribute{}
    \operation{}
    \operation{ToString : unit $\rightarrow$ string}
    \operation{availableMoves : Board $\rightarrow$ Position list}
    \operation{isThreatened : Board : chessPiece : Position $\rightarrow$ bool}
    \operation{}
\end{class}
\begin{class}[text width = 3cm, xshift=-3cm]{Board}{chessPiece.north west}
    \attribute{Item : : chessPiece option with set}
    \operation{static validPositionWrap : Position $\rightarrow$ Position option}
    \operation{ToString : unit $\rightarrow$ string}
    \operation{move : Position : Position $\rightarrow$ unit}
    \operation{getVacantNOccupied : chessPiece : Position list $\rightarrow$ unit}
    \operation{getVacantNNeighbours : chessPiece : Position list $\rightarrow$ unit}
\end{class}
\end{package}
\begin{package}{Pieces}
\begin{class}[text width = 3.3cm, xshift=-4cm]{king}{Board.north west}
%\inherit{chessPiece}
\attribute{nameOfType : string= "king"}
\attribute{candidateRelativeMoves = [[(-1,0)];[(-1,1)];[(0,1)];[(1,1)];
      [(1,0)];[(1,-1)];[(0,-1)];[(-1,-1)]]}
\end{class}
\begin{class}[text width = 3.3cm, yshift=-5mm]{rook}{king.south}
    \inherit{chessPiece}
    \attribute{nameOfType : string= "rook"}
    \attribute{candidateRelativeMoves = List.map (swap List.map [1..7]) indToRel}
\end{class}
\end{package}
\begin{package}{Interactives}
\begin{class}[text width = 3.3cm, yshift=-2cm]{Player}{chessPiece.south}
    \attribute{pieceToMove : chessPiece option = None}
    \operation{nextMove : Board $\rightarrow$ string}
\end{class}
\begin{class}[text width = 3.3cm, yshift=-1cm]{Human}{Player.south}
    \inherit{Player}
\end{class}
\end{package}
\begin{class}[text width = 4cm, xshift=-4cm]{Game}{Player.north west}
    \attribute{player1 : Human}
    \attribute{player2 : Human}
    \attribute{\_board : Board}
    \operation{setup : unit}
    \operation{run : unit}
    \operation{valid : string [] $\rightarrow$ Human $\rightarrow$ bool}
\end{class}
\unidirectionalAssociation {chessPiece}{}{}{Board}
\unidirectionalAssociation{Game}{}{}{chessPiece}
\unidirectionalAssociation{Game}{}{}{Player}
\composition{Game}{}{}{king}
\composition{Game}{}{}{rook}
\composition{Game}{}{}{Human}
\composition{Game}{}{}{Board}
\composition{Player}{}{}{chessPiece}

%% method 1
%\path (king.east) ++(1cm,0) coordinate (m1)
%      (chessPiece.north) ++(0,1.2cm) coordinate(m2);
%\draw [umlcd style inherit line] (chessPiece.north) -- (m2) -| (m1) -- (king.east);

%% method 2 -- requires \usetikzlibrary{calc}
%\draw [umlcd style inherit line]
%     let
%         \p1=(king.east),\p2=(Board.west)
%     in
%     (chessPiece.north) -- ++(0,1.2cm) -| ($(\x1,\y1)!0.5!(\x2,\y1)$) -- (king.east);

%% method 3 -- requires \usetikzlibrary{calc}
%\draw [umlcd style inherit line] (chessPiece.north) -- ++(0,1.2cm) -| ($(king.east)+(1.2cm,0)$) -- (king.east);

%% method 4 -- requires \usetikzlibrary{positioning}
%\coordinate [above left=of Chess] (m3);
%\draw [umlcd style inherit line] (chessPiece) |- (m3) |- (king);

%% method 5
\coordinate (m4) at ([shift={(-4mm,7mm)}]Chess.north west);
\draw [umlcd style inherit line] (chessPiece) |- (m4) |- (king);
\end{tikzpicture}
\end{document}
  • Wow beautiful! This helped so much. Regarding the arrows, could you provide an example such as by making the inheritance arrow going from king to chessPiece go above the chess package and point down to chessPiece? I added an illustration in my question :) – npp Jan 18 at 23:25
  • @npp I updated the answer, showing a few different variations. – Torbjørn T. Jan 19 at 8:45
  • Simply perfect. – npp Jan 19 at 11:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.