10

I need to draw some Entity-Relationship diagrams for my computing coursework, which so far I have written in LaTeX. I could draw them manually using tikz, but that sounds somewhat unpleasant, so I found the er library that tikz has.

This works really well, and I'd like to use it, but it produces Chen-style diagrams by default.

enter image description here

Does anyone know if/how I can produce crow's feet style diagrams with it?

enter image description here

22

The crows foot can be done quite simply with an arrow head. The rest is a matter of simplification using styles and macros, which can be done in many ways. Here is one:

\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=1in
    },
    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=Class] {
    \properties{
        classkey, 
        class_type,
        class_desc
    }
};

\matrix [entity=Product, right=of Class-classkey, entity anchor=Product-classkey]  {
    \properties{
        classkey, 
        prodkey, 
        prod_name, 
        pkg_type
    }
};

\matrix  [entity=Sales, right=of Product-classkey, entity anchor=Sales-classkey]  {
    \properties{
        perkey,
        classkey,
        prodkey,
        prod_name, 
        storekey,
        promokey, 
        quantity,
        dollars
    }
};

\matrix  [entity=Period, right=of Sales-perkey, entity anchor=Period-perkey]  {
    \properties{
        perkey,
        date,
        day,
        week,
        month,
        qtr,
        year
    }
};

\matrix  [entity=Promotion, below=of Period, entity anchor=Promotion-promokey]  {
    \properties{
        promokey,
        promo_type,
        promo_desc,
        value,
        start_date,
        end_date
    }
};

\matrix  [entity=Store, below=of Product, entity anchor=Store-storekey]  {
    \properties{
        storekey,
        mktkey,
        store_type,
        store_name,
        street,
        city,
        state,
        zip
    }
};

\matrix  [entity=Market, left=of Store-mktkey, entity anchor=Market-mktkey]  {
    \properties{
        mktkey,
        hq_city,
        hq_state,
        district,
        region
    }
};

\draw [one to many] (Class-classkey)   to (Product-classkey);
\draw [one to many] (Product-classkey) to (Sales-classkey);
\draw [one to many] (Product-prodkey)  to (Sales-prodkey);
\draw [many to one] (Sales-perkey)     to (Period-perkey);
\draw [one to many] (Market-mktkey)    to (Store-mktkey);
\draw [many to one] (Sales-storekey)   to (Store-storekey);
\draw [many to one] (Sales-promokey)   to (Promotion-promokey);

\end{tikzpicture}

\end{document}

enter image description here

| improve this answer | |
  • I was running into problems when having one node directly below another – zig zag to seems to not cope well in this case. If you're not bothered about having only horizontal and vertical lines (or would rather have nodes vertically adjacent), you can remove the to path line under zig zag to/.style. – Ash Sep 5 '17 at 14:57
2

Following is a "crow's feet" arrow declaration using the PGF 3.x syntax and following the example in section 100.4 of the PGF manual.

\pgfdeclarearrow{
  name = ErdMany,
  parameters = {
    \the\pgfarrowlength
  },
  setup code = {
    % End values
    \pgfarrowssettipend{\pgfarrowlength}
    \pgfarrowssetbackend{0pt}
    \pgfarrowssetlineend{\pgfarrowlength}
    \pgfarrowssetvisualbackend{\pgfarrowlength}
    % Convex hull
    \pgfarrowshullpoint{0pt}{0pt}
    \pgfarrowshullpoint{\pgfarrowlength}{\pgfarrowlength}
    \pgfarrowshullpoint{\pgfarrowlength}{-\pgfarrowlength}
    % Save
    \pgfarrowssavethe\pgfarrowlength
  },
  drawing code = {
    \pgfpathmoveto{\pgfqpoint{\pgfarrowlength}{0.5\pgfarrowlength}}
    \pgfpathlineto{\pgfqpoint{0pt}{0pt}}
    \pgfpathlineto{\pgfqpoint{\pgfarrowlength}{-0.5\pgfarrowlength}}
    \pgfusepathqstroke
  },
  defaults = { length = 10pt }
}

It worked for me as a drop-in replacement of crow's feet under the latest PGF.

| improve this answer | |

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.