3

I've adapted code from this post

The problem that I'm having is that the relations (lines) between tables are crossing over tables rather than going around them.

The MWE is quite long but here it is :

\documentclass[border=0.25in]{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\usetikzlibrary{shadows}
\usetikzlibrary{calc}

\makeatletter
\pgfarrowsdeclare{crow's foot}{crow's foot}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}%
  \pgfarrowsrightextend{+.5\pgflinewidth}%
}
{
  \pgfutil@tempdima=0.5pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0pt}{-6\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-6\pgfutil@tempdima}{0pt}}%
  \pgfpathlineto{\pgfqpoint{0pt}{6\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\tikzset{
    entity/.code={
        \tikzset{
            label=above:#1,
            name=#1,
            inner sep=0pt,
            every entity/.try,
            fill=white,
            general shadow={
                shadow xshift=0.0625in,
                shadow yshift=-0.0625in,
                opacity=0.5,
                fill=black!50
            }
        }%
        \def\entityname{#1}%
    },
    entity anchor/.style={matrix anchor=#1.center},
    every entity/.style={
            draw,
    },
    every property/.style={
        inner xsep=0.25cm, inner ysep=0.125cm, anchor=west, text width=1.5in
    },
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    one to many/.style={
        -crow's foot, zig zag to
    },
    many to one/.style={
        crow's foot-, zig zag to
    },
    many to many/.style={
        crow's foot-crow's foot, zig zag to
    }
}
\def\property#1{\node[name=\entityname-#1, every property/.try]{#1};}
\def\properties{\begingroup\catcode`\_=11\relax\processproperties}
\def\processproperties#1{\endgroup%
    \def\propertycode{}%
    \foreach \p in {#1}{%
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\propertycode%
            \expandafter\expandafter\expandafter{\expandafter\propertycode\expandafter\property\expandafter{\p}\\}%
    }%
    \propertycode%
}

\begin{document}

\begin{tikzpicture}[every node/.style={font=\ttfamily}, node distance=1.25in]

\matrix [entity=Order Form, entity anchor=Order Form-Order ID -> PK]  {
    \properties{
        Order ID -> PK, 
        Cust ID -> FK,
        Order Date
    }
};

\matrix  [entity=Product Table, right=of Order Form-Order ID -> PK, entity anchor=Product Table-Vinyl ID -> PK]  {
    \properties{
        Vinyl ID -> PK,
        title,
        release year,
        record lbl,
        artist,
        album / single,
        cost price,
        Supplier ID -> FK,
        Retail Price,
        Reorder Lvl,
        Stock Lvl
    }
};

\matrix  [entity=Supplier Table, below=of Product Table, entity anchor=Supplier Table-Supplier ID -> PK]  {
    \properties{
        Supplier ID -> PK,
        Supplier Name,
        Sup Add 1,
        Sup Add 2,
        Sup Add 3      
    }
};

\matrix  [entity=Order Details, left=of Supplier Table, entity anchor=Order Details-Vinyl ID -> FK]  {
    \properties{
        Vinyl ID -> FK,
        Order ID -> FK,
        Quantity
    }
};


\matrix  [entity=Customer Table, below=of Supplier Table, entity anchor=Customer Table-Cust ID]  {
    \properties{
        Cust ID,
        First Name,
        Surname,
        Email,
        Postcode,
        Add. Line 1,
        Add. Line 2,
        Add. Line 3
    }
};

\draw [one to many] (Product Table-Vinyl ID -> PK) to (Order Details-Vinyl ID -> FK);
\draw [one to many] (Order Form-Order ID -> PK)   to (Order Details-Order ID -> FK);
\draw [one to many] (Customer Table-Cust ID) to (Order Form-Cust ID -> FK);
\draw [one to many] (Supplier Table-Supplier ID -> PK)  to (Product Table-Supplier ID -> FK);
\end{tikzpicture}

\end{document}

Here's an image of the problem (that might be more instantly clearer) -

enter image description here

I'm not sure how to stop the lines going over the boxes in the way that they currently are. I can't find a value in there to change that prevents this behaviour.

As a side - doing this seems quite labour intensive, if there are any suggestions from others for alternative methods I'd be glad to hear

thank you

2

This is one possible solution. The zig zag to style is set to a default value 0.5 by

zig zag to/.default=0.5

further, one to many and the following two styles also use that default value which causes errors. This proposal removes the zig zag to in the one to many style definition, therefore not using

\draw (<start>) to (<end>)

syntax in the draw commands. But rather use those often seen relative and orthogonal coordinates drawing skills.

\draw (<start>) --++(x,0) |- (<end>);

because the internal labels (<start>) and (<end>) are still valid, containing local coordinates.

enter image description here

Code

\documentclass[border=0.25in]{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\usetikzlibrary{shadows}
\usetikzlibrary{calc}

\makeatletter
\pgfarrowsdeclare{crow's foot}{crow's foot}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}%
  \pgfarrowsrightextend{+.5\pgflinewidth}%
}
{
  \pgfutil@tempdima=0.5pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0pt}{-6\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-6\pgfutil@tempdima}{0pt}}%
  \pgfpathlineto{\pgfqpoint{0pt}{6\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}
\makeatother

\tikzset{
    entity/.code={
        \tikzset{
            label=above:#1,
            name=#1,
            inner sep=0pt,
            every entity/.try,
            fill=white,
            general shadow={
                shadow xshift=0.0625in,
                shadow yshift=-0.0625in,
                opacity=0.5,
                fill=black!50
            }
        }%
        \def\entityname{#1}%
    },
    entity anchor/.style={matrix anchor=#1.center},
    every entity/.style={
            draw,
    },
    every property/.style={
        inner xsep=0.25cm, inner ysep=0.125cm, anchor=west, text width=1.5in
    },
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    one to many/.style={
        -crow's foot, % zig zag to  % disable this `zig zag to` command by mark it out
    },
    many to one/.style={
        crow's foot-, zig zag to
    },
    many to many/.style={
        crow's foot-crow's foot, zig zag to
    }
}
\def\property#1{\node[name=\entityname-#1, every property/.try]{#1};}
\def\properties{\begingroup\catcode`\_=11\relax\processproperties}
\def\processproperties#1{\endgroup%
    \def\propertycode{}%
    \foreach \p in {#1}{%
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\propertycode%
            \expandafter\expandafter\expandafter{\expandafter\propertycode\expandafter\property\expandafter{\p}\\}%
    }%
    \propertycode%
}

\begin{document}

\begin{tikzpicture}[every node/.style={font=\ttfamily}, node distance=1.25in]

\matrix [entity=Order Form, entity anchor=Order Form-Order ID -> PK]  {
    \properties{
        Order ID -> PK, 
        Cust ID -> FK,
        Order Date
    }
};

\matrix  [entity=Product Table, right=of Order Form-Order ID -> PK, entity anchor=Product Table-Vinyl ID -> PK]  {
    \properties{
        Vinyl ID -> PK,
        title,
        release year,
        record lbl,
        artist,
        album / single,
        cost price,
        Supplier ID -> FK,
        Retail Price,
        Reorder Lvl,
        Stock Lvl
    }
};

\matrix  [entity=Supplier Table, below=of Product Table, entity anchor=Supplier Table-Supplier ID -> PK]  {
    \properties{
        Supplier ID -> PK,
        Supplier Name,
        Sup Add 1,
        Sup Add 2,
        Sup Add 3      
    }
};

\matrix  [entity=Order Details, left=of Supplier Table, entity anchor=Order Details-Vinyl ID -> FK]  {
    \properties{
        Vinyl ID -> FK,
        Order ID -> FK,
        Quantity
    }
};


\matrix  [entity=Customer Table, below=of Supplier Table, entity anchor=Customer Table-Cust ID]  {
    \properties{
        Cust ID,
        First Name,
        Surname,
        Email,
        Postcode,
        Add. Line 1,
        Add. Line 2,
        Add. Line 3
    }
};

\draw [one to many] (Product Table-Vinyl ID -> PK) --++(-2.7,0) |-  (Order Details-Vinyl ID -> FK);
\draw [one to many] (Order Form-Order ID -> PK)   --++(-3,0) |- (Order Details-Order ID -> FK);
\draw [one to many] (Customer Table-Cust ID) --++(-2.7,0) |-(Order Form-Cust ID -> FK);
\draw [one to many] (Product Table-Supplier ID -> FK) --++(3,0) |- (Supplier Table-Supplier ID -> PK) ;
\end{tikzpicture}

\end{document}
|improve this answer|||||
  • Hey @Jesse that's ace - works a treat... this stuffs a bit over my head atm and I'm trying to finish this doc off, looking forward to going over it all with a bit of a finer comb later on. thank you though! – baxx Dec 20 '14 at 19:36
  • Welcome. Glad it helps. – Jesse Dec 21 '14 at 0:37
1

Your zig zag to works well only between points with different x coordinate.

You ca define another style, for example zig zig to that works well for points with the same x and use it to define new one to many bis.

I have changed one to many by adding access to the parameter of zig zag to. In this way edges don't overlap.

Here is the code :

\documentclass[border=0.25in]{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\usetikzlibrary{shadows}
\usetikzlibrary{calc}

\makeatletter
\pgfarrowsdeclare{crow's foot}{crow's foot}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}%
  \pgfarrowsrightextend{+.5\pgflinewidth}%
}
{
  \pgfutil@tempdima=0.5pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0pt}{-6\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-6\pgfutil@tempdima}{0pt}}%
  \pgfpathlineto{\pgfqpoint{0pt}{6\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\tikzset{
    entity/.code={
        \tikzset{
            label=above:#1,
            name=#1,
            inner sep=0pt,
            every entity/.try,
            fill=white,
            general shadow={
                shadow xshift=0.0625in,
                shadow yshift=-0.0625in,
                opacity=0.5,
                fill=black!50
            }
        }%
        \def\entityname{#1}%
    },
    entity anchor/.style={matrix anchor=#1.center},
    every entity/.style={
            draw,
    },
    every property/.style={
        inner xsep=0.25cm, inner ysep=0.125cm, anchor=west, text width=1.5in
    },
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    zig zig to/.style={
        to path={(\tikztostart) -| ++(#1,0) |- (\tikztotarget)}
    },
    zig zig to/.default=2.5cm,
    one to many/.style={
        -crow's foot, zig zag to=#1
    },
    one to many bis/.style={
        -crow's foot, zig zig to=#1
    },
    many to one/.style={
        crow's foot-, zig zig to=#1
    },
    many to many/.style={
        crow's foot-crow's foot, zig zag to=#1
    }
}
\def\property#1{\node[name=\entityname-#1, every property/.try]{#1};}
\def\properties{\begingroup\catcode`\_=11\relax\processproperties}
\def\processproperties#1{\endgroup%
    \def\propertycode{}%
    \foreach \p in {#1}{%
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\propertycode%
            \expandafter\expandafter\expandafter{\expandafter\propertycode\expandafter\property\expandafter{\p}\\}%
    }%
    \propertycode%
}

\begin{document}

\begin{tikzpicture}[every node/.style={font=\ttfamily}, node distance=1.25in]

\matrix [entity=Order Form, entity anchor=Order Form-Order ID -> PK]  {
    \properties{
        Order ID -> PK,
        Cust ID -> FK,
        Order Date
    }
};

\matrix  [entity=Product Table, right=of Order Form-Order ID -> PK, entity anchor=Product Table-Vinyl ID -> PK]  {
    \properties{
        Vinyl ID -> PK,
        title,
        release year,
        record lbl,
        artist,
        album / single,
        cost price,
        Supplier ID -> FK,
        Retail Price,
        Reorder Lvl,
        Stock Lvl
    }
};

\matrix  [entity=Supplier Table, below=of Product Table, entity anchor=Supplier Table-Supplier ID -> PK]  {
    \properties{
        Supplier ID -> PK,
        Supplier Name,
        Sup Add 1,
        Sup Add 2,
        Sup Add 3
    }
};

\matrix  [entity=Order Details, left=of Supplier Table, entity anchor=Order Details-Vinyl ID -> FK]  {
    \properties{
        Vinyl ID -> FK,
        Order ID -> FK,
        Quantity
    }
};


\matrix  [entity=Customer Table, below=of Supplier Table, entity anchor=Customer Table-Cust ID]  {
    \properties{
        Cust ID,
        First Name,
        Surname,
        Email,
        Postcode,
        Add. Line 1,
        Add. Line 2,
        Add. Line 3
    }
};

\draw [one to many=.45 ] (Product Table-Vinyl ID -> PK) to (Order Details-Vinyl ID -> FK);
\draw [one to many bis=-3cm] (Order Form-Order ID -> PK)   to (Order Details-Order ID -> FK);
\draw [one to many] (Customer Table-Cust ID) to (Order Form-Cust ID -> FK);
\draw [one to many bis=3cm] (Supplier Table-Supplier ID -> PK)  to (Product Table-Supplier ID -> FK);
\end{tikzpicture}

\end{document}

enter image description here

|improve this answer|||||
  • @user3130747 you are welcom. – Kpym Dec 20 '14 at 20:59

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.