9

I am trying to draw a SWOT matrix using TikZ. Clearly the procedure that I present in the MWE is not optimized. Also the text (namely on the left side) is not correctly aligned.

enter image description here

\documentclass[10pt]{standalone}
\usepackage{times}

\usepackage{tikz}
\usetikzlibrary{fit}
\usetikzlibrary{calc}
\usetikzlibrary{intersections}
\usetikzlibrary{backgrounds}

\tikzset{desc/.style={outer sep=0pt,inner sep=0pt,text centered,font=\scriptsize,fill=black!10}}

\newcommand{\texta}{Helpful\\ \tiny (to achieve the objective)}
\newcommand{\textb}{Harmful\\ \tiny (to achieve the objective)}
\newcommand{\textc}{\rotatebox[origin=r]{90}{\shortstack{Internal origin\\ \tiny (product\slash company attributes)}}}
\newcommand{\textd}{\rotatebox[origin=r]{90}{\shortstack{External origin\\ \tiny (environment\slash market attributes)}}}

\begin{document}
\begin{tikzpicture}[x=3cm,y=3cm]
\coordinate (c1) at (0,0);
\coordinate (c2) at (2,0);
\coordinate (c3) at (2,2);
\coordinate (c4) at (0,2);
\coordinate (c5) at ($(c1)!0.5!(c2)$);
\coordinate (c6) at ($(c2)!0.5!(c3)$);
\coordinate (c7) at ($(c3)!0.5!(c4)$);
\coordinate (c8) at ($(c4)!0.5!(c1)$);
\coordinate (c8) at ($(c4)!0.5!(c1)$);
\draw (c1) --+ (c2) --+ (c3) --+ (c4) -- cycle;
\path [name path=c5--c7,draw] (c5) -- (c7);
\path [name path=c6--c8,draw] (c6) -- (c8);
\coordinate [name intersections={of=c5--c7 and c6--c8,by=c9}];
\node [outer sep=0pt,inner sep=0pt,fit={(c8) (c9) (c7) (c4)}] (S){Strengths};
\node [outer sep=0pt,inner sep=0pt,fit={(c9) (c6) (c3) (c7)}] (W){Weaknesses};
\node [outer sep=0pt,inner sep=0pt,fit={(c1) (c5) (c9) (c8)}] (O){Opportunities};
\node [outer sep=0pt,inner sep=0pt,fit={(c5) (c2) (c6) (c9)}] (T){Threats};
%%%%
\coordinate[yshift=1cm] (u4) at (S.north west);
\coordinate[yshift=1cm] (u3) at (W.north east);
\coordinate[yshift=1cm] (u7) at (W.north west);
\draw (c4) -- (u4) -- (u3) -- (c3);
\draw (c7) -- (u7);
\begin{pgfonlayer}{background}
\node [desc,fit={(c4) (u4) (u7) (c7)}] {\texta}; 
\node [desc,fit={(c7) (u7) (u3) (c3)}] {\textb}; 
\end{pgfonlayer}{background}
%%%%
\coordinate[xshift=-1cm] (l4) at (S.north west);
\coordinate[xshift=-1cm] (l8) at (S.south west);
\coordinate[xshift=-1cm] (l1) at (O.south west);
\draw (c4) -- (l4) -- (l1) -- (c1);
\draw (c8) -- (l8);
\begin{pgfonlayer}{background}
\node [desc,fit={(c4) (l4) (l8) (c8)}] {\textc}; 
\node [desc,fit={(c8) (l8) (l1) (c1)}] {\textd}; 
\end{pgfonlayer}
\end{tikzpicture}
\end{document}
2
  • Is there more that will eventually be added to the diagram? Otherwise, you could just use a table? Commented Apr 29, 2013 at 4:26
  • I used TikZ because I wanted to have full control of all cells in terms of width and height. In tabular environment I can use p{} column type to have a fixed width, but for the height I would probably need to use a minipage for each cell of that table, which I am not quite sure if it is desirable.
    – cacamailg
    Commented Apr 29, 2013 at 4:45

1 Answer 1

12

You can use a matrix (of nodes). If you are sure that minimum width and minimum height are large enough for its contents, that will be its size. With a matrix like that you don't need to draw lines, because, node borders provide them. And with a column(row) sep=-.5\pgflinewidth, node borders will be drawn one over the other.

\documentclass[10pt,tikz]{standalone}
\usepackage{times} % for the font

\usetikzlibrary{matrix}

\newcommand{\texta}{Helpful\\[-1ex] \tiny{(to achieve the objective)}}
\newcommand{\textb}{Harmful\\[-1ex] \tiny{(to achieve the objective)}}
\newcommand{\textcn}{Internal origin\\[-1ex] \tiny{(product\slash company attributes)}}
\newcommand{\textdn}{External origin\\[-1ex] \tiny{(environment\slash market attributes)}}


\begin{document}
\begin{tikzpicture}[
    any/.style={draw,minimum width=3cm,minimum height=3cm,text width=2.5cm,align=center},
    header/.style={any,minimum height=1cm,fill=black!10},
    leftcol/.style={header,rotate=90}
]

\matrix (SWOT) [matrix of nodes,nodes={any,anchor=center},column sep=-1\pgflinewidth,row sep=-1\pgflinewidth,inner sep=0pt]
{
 &|[header]| {\texta} & |[header]| {\textb} \\
|[leftcol]| {\textcn} & Strengths & Weakness \\
|[leftcol]| {\textdn} & Opportunities & Threats \\
};
\end{tikzpicture}
\end{document}

enter image description here

Qrrbrbirlbel suggested several improvements to previous code:

1 - It's possible to define particular row/column/cell styles and avoid using syntax |[stuff]|. Something like row 1/.style={stuff} means to apply .append style=stuff to all nodes in first row. 2 - I wrongly corrected OP's code for \text.. changing \tiny (...) with \tiny{(...)}. 3 - Addition of \par at end of every \text.. command. It will produce a different vertical alignment inside header cells.

Next you have resulting code and figure:

\documentclass[10pt,tikz]{standalone}
\usepackage{times}

\usepackage{tikz}
\usetikzlibrary{matrix}

\newcommand{\texta}{Helpful\\ \tiny (to achieve the objective)\par}
\newcommand{\textb}{Harmful\\ \tiny (to achieve the objective)\par}
\newcommand{\textcn}{Internal origin\\ \tiny (product\slash company attributes)\par}
\newcommand{\textdn}{External origin\\ \tiny (environment\slash market attributes)\par}


\begin{document}
\begin{tikzpicture}[
    any/.style={draw,minimum width=3cm,minimum height=3cm,%
                 text width=2.5cm,align=center,outer sep=0pt},
    header/.style={any,minimum height=1cm,fill=black!10},
    leftcol/.style={header,rotate=90}
]

\matrix (SWOT) [matrix of nodes,nodes={any,anchor=center},%
                column sep=-\pgflinewidth,%
                row sep=-\pgflinewidth,%
                row 1/.style={nodes=header},%
                column 1/.style={nodes=leftcol},
                inner sep=0pt]
{
          & {\texta} & {\textb} \\
{\textcn} & Strengths & Weakness \\
{\textdn} & Opportunities & Threats \\
};
\end{tikzpicture}
\end{document}

enter image description here

6
  • Thanks for your answer. The problem with that approach is that: the very outside lines do not have the same thickness as the inner lines.
    – cacamailg
    Commented Apr 29, 2013 at 9:51
  • @cacamailg: You're right. I've changed -.5\pgflinewidth with -\pgflinewidth. This solution will work if all cells have same color border.
    – Ignasi
    Commented Apr 29, 2013 at 15:26
  • Add column 1/.append style={nodes=leftcol}, row 1/.append style={nodes=header} to the options of the \matrix and you can drop the |[<stuff>]|. (The braces are still needed because of the inner \\.) By the way, \tiny is not a macro that takes an argument but a parameter-less switch. Op’s code was correct in this instance. Through a final \par in these cells to see a different in vertical spacing … Commented Apr 29, 2013 at 15:37
  • I edited the code, now lines are ok :). Further I will improve with the @Qrrbrbirlbel sugestion. Thanks to all!
    – cacamailg
    Commented Apr 29, 2013 at 16:11
  • @cacamailg: Thank you for your edition. I've added Qrrbrbirlbel suggestions but leaved yours because vertical space inside cells is different. By the way, you don't need 1 in front of \pgflinewidth.
    – Ignasi
    Commented Apr 30, 2013 at 7:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .