% Copyright 2011 by Daniele Pighin % % This file may be distributed and/or modified % % 1. under the LaTeX Project Public License and/or % 2. under the GNU Public License. % % See the file doc/generic/tikz-dependency/licenses/LICENSE for more details. % % Changelog % % 1.2 (Nov 3, 2016) % - It's been a while :) Integrated a patch submitted by Jan Strunk % (thanks a lot Jan!) fixing a bug with the behavior of "edge end x offset". % % 1.1 (Jan 17, 2012) % - Added the possibility to use simple arcs as edges (keys: arc edge/segmented edge) % - Added "edge start x offset" and "edge end x offset" to fine tune edge start/end point position % - Added \depstyle to define styles more easily % - Added "simple" theme, based on the parse on page 1 of [Nivre and McDonald, 2008 ACL-HLT] % - Added instructions to draw bubble parses % - Fixed bug that would cause groupedges not to be straight under some circumstances; % % 1.0 (Nov 26, 2011) % - First public release \ProvidesPackage{tikz-dependency}[2011/01/08 v1.1 Macros to draw dependency trees] \NeedsTeXFormat{LaTeX2e}[1999/12/01] \RequirePackage{tikz,environ} \usetikzlibrary{matrix,arrows,backgrounds,calc,patterns,positioning,fit,shapes} \pgfdeclarelayer{depgroups} \pgfsetlayers{depgroups,main} \newcounter{dt@labelid} \newif\ifdt@linkbelow \newif\ifdt@arcedge \tikzset{ /depgraph/.cd, /depgraph/.search also = {/tikz}, dep id/.code = {\def\dt@depid{#1}}, dep id = dependency, % fix the distance of the edge edge height/.code = {\pgfmathsetlengthmacro{\dt@linkheight}{#1}}, edge height = 0pt, % the distant of the horizontal line of the edge style for two adjacent words edge unit distance/.code = {\pgfmathsetlengthmacro{\dt@linkstep}{#1}}, edge unit distance = 3ex, % the horizontal offset defining the trapezoidal look edge slant/.code = {\pgfmathsetlengthmacro{\dt@linkslant}{#1}}, edge slant = 3pt, % the horizontal offset defining the starting/ending position of the edge style edge horizontal padding/.code = {\pgfmathsetlengthmacro{\dt@linkoffset}{#1}}, edge horizontal padding = 4pt, % vertical offset of the edge style from the word edge vertical padding/.code = {\pgfmathsetlengthmacro{\dt@linkdist}{#1}}, edge vertical padding = 0ex, % should links be placed above or below the sentence edge below/.is if = dt@linkbelow, edge below/.default=true, edge above/.code = {\dt@linkbelowfalse}, % arc edge arc edge/.is if = dt@arcedge, segmented edge/.code = {\dt@arcedgefalse}, arc angle/.store in = \dt@arcangle, arc angle = 60, % an explicit offset to compensate the x position of the edge edge start x offset/.code = {\pgfmathsetlengthmacro{\dt@EdgeStartOffsetX}{#1}}, edge start x offset = 0, edge end x offset/.code = {\pgfmathsetlengthmacro{\dt@EdgeEndOffsetX}{#1}}, edge end x offset = 0, % the layer that links should connect % (should be set to "1" for edge above, and to the number of rows % in the matrix for edge below) target layer/.store in = \dt@tgtlayer, target layer/.default = 0, target layer = 0, % styling options reserved/edge style/.style = {->, >=stealth, black, solid, rounded corners = 2, line cap = round, segmented edge}, edge style/.style = {reserved/edge style/.append style = {#1}}, reserved/label style/.style = { anchor = mid, draw, solid, black, scale = .7, text height = 1.5ex, text depth = 0.25ex, % needed to center text vertically inner sep=.5ex, outer sep = 0pt, rounded corners = 2pt, text = black, fill = white}, label style/.style = {reserved/label style/.append style = {#1}}, hide label/.style = {reserved/label style/.append style = {opacity = 0, text opacity = 0}}, show label/.style = {reserved/label style/.append style = {opacity = 1, text opacity = 1}}, text only label/.style = {reserved/label style/.append style = {opacity=0, text opacity=1}}, reserved/text style/.style = { text height=1.5ex, text depth = 0.25ex, % needed to center text vertically inner sep = .5ex}, text style/.style = {reserved/text style/.append style = {#1}}, % group styling reserved/group style/.style = { inner sep = 0, draw, solid, outer sep = .5ex, rounded corners = 2pt}, group style/.style = {reserved/group style/.append style = {#1}}, % themes for text text theme/.is choice, text theme/default/.style = {text style={black}}, text theme/brazil/.style = {text style={blue!60!black}}, text theme/iron/.style = {text style={black!80}}, text theme/copper/.style = {text style={brown!60!black}}, text theme/night/.style = {text style={black}}, text theme/grassy/.style = {text style={green!40!black}}, text theme/simple/.style = {text style={black}}, % themes for labels label theme/.is choice, label theme/default/.style = {label style={fill=white, draw=black}}, label theme/night/.style = {label style={text=white, fill=black, font=\bfseries}}, label theme/brazil/.style = {label style={thick, black, fill=yellow, text=black, font=\bfseries}}, label theme/iron/.style = {label style={top color=black!60, bottom color=black!80, draw=black!80, text=white, font=\bfseries}}, label theme/copper/.style = {label style={top color=brown!80!pink, bottom color=brown!60!black, draw=brown!80, text=white, font=\bfseries}}, label theme/grassy/.style = {label style={bottom color=green!60!black, top color=green!20!black, draw=green!40!black, text=white, font=\bfseries}}, label theme/simple/.style = {label style={draw=none,fill=none,above,font=\scriptsize}}, % themes for edges edge theme/.is choice, edge theme/default/.style = {edge style={thin,black}}, edge theme/night/.style = {edge style={thick}}, edge theme/brazil/.style = {edge style={thick,green!60!black}}, edge theme/iron/.style = {edge style={thick, black!80}}, edge theme/copper/.style = {edge style={thick, brown!80}}, edge theme/grassy/.style = {edge style={thick, green!40!black}}, edge theme/simple/.style = {arc edge, arc angle=79}, % themes styles theme/.style = {label theme = #1, edge theme = #1, text theme = #1}, } \newcommand{\depstyle}[2]{\tikzset{#1/.style = {/depgraph/.cd, #2}}} \newenvironment{dependency}[1][]{% \begin{tikzpicture}[/depgraph/.cd, #1] \begin{scope} }{% \end{scope}% \end{tikzpicture}% } \NewEnviron{deptext}[1][]{% \begin{scope} \matrix (\dt@depid)[% nodes = {/depgraph/reserved/text style}, column sep = 0, row sep = -.5ex, matrix of nodes, ampersand replacement = \&, nodes in empty cells, #1] { \BODY% };% \pgfmathtruncatemacro\dt@tmp{\pgfmatrixcurrentrow} \xdef\dt@numrows{\dt@tmp} \end{scope}% } \newcommand{\depkeys}[1]{\tikzset{/depgraph/.cd, #1}} \newcommand{\settgtlayer}{% \ifnum\dt@tgtlayer=0% \ifdt@linkbelow% \pgfmathtruncatemacro{\dt@tgtlayer}{\dt@numrows}% \else% \pgfmathtruncatemacro{\dt@tgtlayer}{1}% \fi% \fi% } \newcommand{\deproot}[3][]{% options, root offset, root reserved/label style \begin{scope} \depkeys{#1} \pgfmathsetmacro{\offa}{#2} \settgtlayer \def\anchorpoint{north} \ifdt@linkbelow \def\anchorpoint{south} \fi \def\source{\dt@depid-\dt@tgtlayer-#2} \ifdim\dt@linkheight=0pt \pgfmathsetmacro{\distance}{\dt@linkstep * 4} \else \pgfmathsetlengthmacro{\distance}{\dt@linkheight} \fi \pgfmathsetlengthmacro{\dt@startdist}{\dt@linkdist} \ifdt@linkbelow \pgfmathsetmacro{\distance}{-(\dt@linkstep * 4)} \pgfmathsetlengthmacro{\dt@startdist}{-\dt@startdist} \fi \node at (\source) (\rootref) [yshift=\distance, /depgraph/.cd, reserved/label style, #1] {#3}; \draw [/depgraph/.cd, reserved/edge style, #1] (\rootref) -- ($(\source.\anchorpoint) + (0, \dt@startdist)$); \end{scope} } \newcommand{\depedge}[4][]{% options, source offset, target offset, dep name \begin{scope} \depkeys{#1} \pgfmathsetmacro{\offa}{#2} \pgfmathsetmacro{\offb}{#3} \settgtlayer \def\source{\wordref{\dt@tgtlayer}{#2}} \def\dest{\wordref{\dt@tgtlayer}{#3}} \def\depname{#4} \ifdim\dt@linkheight=0pt \pgfmathsetlengthmacro{\distance}{abs(\offb - \offa)*\dt@linkstep} \else \pgfmathsetlengthmacro{\distance}{\dt@linkheight} \fi \groupedge[#1]{\source}{\dest}{\depname}{\distance} \end{scope}} \newlength{\xca} \newlength{\yca} \newlength{\xcb} \newlength{\ycb} \newcommand{\wordref}[2]{\dt@depid-#1-#2} \newcommand{\rootref}{\dt@depid-root} \newcommand{\matrixref}{\dt@depid} % \storelabelnode % % \edef#1 the name of the last reserved/label style, stored in \dt@lastlabel % % #1 - a macro \newcommand{\storelabelnode}[1]{\edef#1{\dt@lastlabel}} \newcommand{\storefirstcorner}[1]{\edef#1{\dt@lastlabel-edge-first-corner}} \newcommand{\storesecondcorner}[1]{\edef#1{\dt@lastlabel-edge-second-corner}} \newcommand{\wordgroup}[5][]{% options, layer, col-start, col-end, identifier \begin{scope}[/depgraph/.cd, #1] \pgfonlayer{depgroups} \node (#5) [fit = (\wordref{#2}{#3}) (\wordref{#2}{#4}), /depgraph/.cd, reserved/group style, #1] {}; \endpgfonlayer \end{scope} } \newcommand{\groupedge}[5][]{% options, source, target, depname, distance \begin{scope}[/depgraph/.cd, #1] \def\anchorpoint{north} \ifdt@linkbelow \def\anchorpoint{south} \fi \pgfextractx{\xca}{\pgfpointanchor{#2}{\anchorpoint}} \pgfextractx{\xcb}{\pgfpointanchor{#3}{\anchorpoint}} \pgfextracty{\yca}{\pgfpointanchor{#2}{\anchorpoint}} \pgfextracty{\ycb}{\pgfpointanchor{#3}{\anchorpoint}} \pgfmathsetlengthmacro{\ydiff}{\yca-\ycb} \ifdim\xca>\xcb \pgfmathsetlengthmacro{\doff}{-\dt@linkoffset} \pgfmathsetlengthmacro{\dslant}{-\dt@linkslant} \else \pgfmathsetlengthmacro{\doff}{\dt@linkoffset} \pgfmathsetlengthmacro{\dslant}{\dt@linkslant} \fi \addtocounter{dt@labelid}{1} \xdef\dt@lastlabel{\dt@depid-\the\value{dt@labelid}} \pgfmathsetlengthmacro{\dt@startdist}{\dt@linkdist} \pgfmathsetlengthmacro{\dt@enddist}{#5} \ifdt@linkbelow \pgfmathsetlengthmacro{\dt@startdist}{-\dt@startdist} \pgfmathsetlengthmacro{\dt@enddist}{-\dt@enddist} \fi % Calculate edge anchors. -edge-first-corner and -edge-second-corner are only % meaningful for segmented edge, but we also draw the nodes for arc edge, someone % may always find these anchors useful... \node (\dt@lastlabel-edge-origin) [coordinate] at ($(#2.\anchorpoint) + (\doff,\dt@startdist) + (\dt@EdgeStartOffsetX,0)$) {}; \node (\dt@lastlabel-edge-first-corner) [coordinate] at ($(\dt@lastlabel-edge-origin) + (\dslant,\dt@enddist)$) {}; \node (\dt@lastlabel-edge-second-corner) [coordinate] at ($(#3.\anchorpoint) + (\dt@EdgeEndOffsetX,0) + (-\dslant,\dt@enddist+\dt@startdist+\ydiff)$) {}; \node (\dt@lastlabel-edge-endpoint) [coordinate] at ($(#3.\anchorpoint) + (0,\dt@startdist) + (\dt@EdgeEndOffsetX,0)$) {}; \ifdt@arcedge % link above, left to right \pgfmathsetmacro{\dt@arcin}{180-\dt@arcangle} \pgfmathsetmacro{\dt@arcout}{\dt@arcangle} \ifdt@linkbelow % link below \pgfmathsetmacro{\dt@arcin}{-\dt@arcin} \pgfmathsetmacro{\dt@arcout}{-\dt@arcout} \fi \ifdim\xca>\xcb % right to left \pgfmathsetmacro{\dt@temp}{\dt@arcin} \pgfmathsetmacro{\dt@arcin}{\dt@arcout} \pgfmathsetmacro{\dt@arcout}{\dt@temp} \fi %\draw [/depgraph/.cd, reserved/edge style, rounded corners = #5/5, #1] \draw [out=\dt@arcout, in=\dt@arcin,/depgraph/.cd, reserved/edge style, rounded corners = #5/5, #1] (\dt@lastlabel-edge-origin) to node (\dt@lastlabel) [/depgraph/.cd, #1, reserved/label style] {#4} (\dt@lastlabel-edge-endpoint); \else \draw [/depgraph/.cd, reserved/edge style, rounded corners = #5/5, #1] (\dt@lastlabel-edge-origin) -- (\dt@lastlabel-edge-first-corner) -- (\dt@lastlabel-edge-second-corner) -- (\dt@lastlabel-edge-endpoint); \node (\dt@lastlabel) [/depgraph/.cd, #1, reserved/label style] at ($ .5*(\dt@lastlabel-edge-second-corner) + .5*(\dt@lastlabel-edge-first-corner) $) {#4}; \fi \end{scope} }