我有 7 个类,想用 Latex 制作这些类的 UML 图。我确实设法编写了代码,但请看一下结果(我甚至尝试过重新缩放和重新排列): 您甚至无法识别显示关系的所有线条。如您所见,UML 非常混乱,所以我想知道是否可以在 Latex 中制作此 UML,使其看起来更清晰?代码:
\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}
答案1
这个看起来怎么样?主要是我只是重新定位了一些东西,改变了一些text width
s 和字体大小。请注意,我将一些类相对于其他类进行了定位(请参阅有没有什么方法可以使用 LaTeX 创建 UML 而无需提供 (x,y) 坐标?了解更多信息),这使得对齐事物变得更容易。
如果您有修改建议,请随时在评论中添加。例如,当然可以以不同的方式绘制各种箭头,它们不必是直线,但可能需要更多的手动工作,而不是pgf-umlcd
宏(\composition
等等)。
下面的代码展示了在包之间创建继承箭头的几种方法king
。chessPiece
这Chess
是使用标准 TikZ\draw
宏“手动”完成的。
它们主要利用在路径的角点定义命名坐标,并使用-|
/|-
路径规范(参见TikZ:箭头的 |- 符号到底起什么作用?) 来绘制线条。为了获得正确的外观,我添加了umlcd style inherit line
样式。有些方法需要特定的 TikZ 库,在评论中提到。
\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}