4

I would like to reproduce a hierarquical semantic network like this (Memory and Learning, from brain to behavior", Mark A. Gluck)

Hierarquical semantic network. (Memory and Learning, from brain to behavior, Mark A. Gluck

My main problem is to add the lateral information in each box. Perhaps, the best way is to write a function in which the arguments should be the box side and the properties list.

My code:

\startMPdefinitions
input boxes;
\stopMPdefinitions


\starttext


\startMPcode

%% boxes names
boxit.animal    ("Animal");
boxit.fish        ("Fish");
boxit.bird       ("Bird");
boxit.mammal   ("Mammal");
boxit.canary("Canary");
boxit.ostrich("Ostrich");
boxit.dog("Dog");
boxit.dolphin("dolphin");
boxit.chi("Chihuahua");
boxit.dal("Dalmation");
boxit.fido("Fido");


%% boxes positions

fish.c = origin; 
fish.c = animal.c - 60 up;
animal.c = .5[bird.c,mammal.c] + 60 up; 
bird.c - fish.c= fish.c - mammal.c = 90 left;  
ostrich.c = bird.c + 60 down;
canary.c = ostrich.c + 50 left;
dolphin.c = mammal.c + 20 right + 60 down;
dog.c = dolphin.c + 50 left;
chi.c = dog.c + 50 left + 60 down;
dal.c = dog.c + 50 right + 60 down;
fido.c = dal.c + 60 down;

forsuffixes x = animal, fish, mammal, bird, ostrich, canary, dog, dolphin, chi, dal, fido:
drawboxed(x);
endfor

%%% arrows and paths
path p[];
p1 = animal.sw -- bird.ne;
p2 = animal.s--fish.n;
p3 = animal.se -- mammal.nw;
p4 = bird.s--ostrich.n;
p5 = bird.s--canary.ne;
p6=mammal.s--dog.n;
p7=dog.s--chi.n;
p8=dog.s--dal.n;
p9=dal.s--fido.n;
p10=mammal.s--dolphin.n;

for i=1 upto 10:
drawarrow p[i];
endfor 

\stopMPcode


\stoptext

My output:

enter image description here

Thanks to all

  • Do you want this in metapost or tikz/forest? Or both? – Alenanno Apr 18 '16 at 18:46
  • Both, please. Can arise some beautiful solutions in the tikz side. – Jorge Apr 18 '16 at 19:01
  • You should post your code as an answer. Right now, it isn't clear to people searching that there are 2 answers and not one. – cfr Apr 21 '16 at 23:56
6

I'm posting this because you indicated an interest in seeing a TikZ/Forest version. Forest is the most flexible and powerful TikZ-based method to draw trees. However, I'm not sure this is compatible with ConTeXt, even though TikZ itself is. Obviously you would not need inputenc, for example, which I'm using here to handle the unicode quotation marks. These could be replaced by TeX mark-up if preferred. I'm just used to typing them this way. But Forest itself seems to be a LaTeX package ....

The tree uses forest and the custom format of the tree uses the backgrounds TikZ library. Quotation marks are handled here by csquotes, but this is obviously optional.

\begin{forest}

The tree's preamble should be moved into a Forest style if it is to be used for several trees. Here, we simply customise the one particular tree.

  for tree={

The quoted attributes are not nodes but are added later. So we need to make the tree a bit roomier than it would otherwise be.

    fit=band,
    s sep+=20pt,

This ensures that when a parent has an odd number of children (e.g. 3), it is aligned with the middle one (e.g. the second).

    if={isodd(n_children)}{%
      calign primary child={int((n_children()+1)/2)},
      calign=child,
    }{},

Here's our custom edge configuration. The shortening is actually lengthening the lines to compensate for the use of rounded corners. To avoid the edges being drawn over the nodes when not draw through a corner, we draw the edges on background layer, behind the nodes.

    edge={ultra thick, orange!50!yellow, shorten <=-5pt, shorten >=-5pt},
    edge path={%
      \noexpand\scoped[on background layer]
      \noexpand\path [\forestoption{edge}] (!u) -- ()\forestoption{edge label};
    },

Custom node configuration with rounded corners, a thick, coloured border and a light fill.

    draw=orange!50!yellow,
    rounded corners=5pt,
    ultra thick,
    inner color=orange!75!yellow!10,
    outer color=orange!75!yellow!25,

We use sans for the node text and fixed height/depth so that our nodes look nicely aligned.

    font=\sffamily,
    text height=2ex,
    text depth=.5ex,
  },

This is just a TikZ style, my pins, for the quoted bits which is similar to the configuration for the main nodes.

  /tikz/my pins/.style={font=\sffamily\footnotesize, text height=1ex, text depth=.25ex, inner sep=1pt},

A right pin is a custom TikZ node added to the right of one of the main nodes. It takes 2 arguments separated by a colon: <angle>:<text>.

  right pin/.style args={#1:#2}{%
    tikz+={%
      \scoped[on background layer]\draw [thick, draw=orange!50!yellow, shorten <=-5pt] () -- ++(#1:35pt) node [right, my pins] {‘#2’};
    }
  },

right pins takes a list of <angle>:<text> arguments to be passed to right pin.

  right pins/.style={%
    split={#1}{,}{right pin}
  },

left pin and left pins are just like right pin and right pins but, unsurprisingly, for quoted text on the left rather than the right of a main node.

  left pin/.style args={#1:#2}{%
    tikz+={%
      \scoped[on background layer]\draw [thick, draw=orange!50!yellow, shorten <=-5pt] () -- ++(#1:35pt) node [my pins, left] {‘#2’};
    }
  },
  left pins/.style={%
    split={#1}{,}{left pin}
  },

That's the tree's preamble done. Now for the tree specification, starting with the root node which has 3 attributes quoted to the right. So we use `right pins={:,:,:}.

  [Animal, right pins={40:can move,20:eats,0:reproduces}

We continue with a node which has 3 attributes quoted to the left by using left pins in the same way.

    [Bird, left pins={-160:lays eggs,180:is warm-blooded,160:has feathers}

The next 2 nodes have 2 left pins and 2 right pins respectively.

      [Canary, left pins={-170:is small,170:works in coal mines}
      ]
      [Ostrich, right pins={-10:cannot fly,10:is quite large}
      ]
    ]

We continue, completing and annotating the tree in the same way.

    [Fish, right pins={-10:has gills,10:can swim}
    ]
    [Mammal, right pins={-15:has fur,5:produces milk,25:bears live young,45:breathes air}
      [Dog, left pins={170:barks,-170:wags tail}
        [Chihuahua, left pins={-170:is teeny,170:is fierce}
        ]
        [Dalmation, right pins={-10:has 100 siblings,10:is spotted}
          [Fido, right pins={-10:has red kennel,10:is scared of mice}
          ]
        ]
      ]
      [Dolphin, right pins={-10:is highly social,10:lives in pods}
      ]
    ]
  ]

Close out the environment

\end{forest}

and we're done.

semantic network

Complete code:

\documentclass[border=10pt,tikz,multi]{standalone}
\usepackage{forest}
\usepackage[utf8]{inputenc}
\usepackage{csquotes}
   \MakeAutoQuote{‘}{’}
   \MakeAutoQuote*{“}{”}
\usetikzlibrary{backgrounds}
\begin{document}
\begin{forest}
  for tree={
    fit=band,
    s sep+=20pt,
    if={isodd(n_children)}{%
      calign primary child={int((n_children()+1)/2)},
      calign=child,
    }{},
    edge={ultra thick, orange!50!yellow, shorten <=-5pt, shorten >=-5pt},
    edge path={%
      \noexpand\scoped[on background layer]
      \noexpand\path [\forestoption{edge}] (!u) -- ()\forestoption{edge label};
    },
    draw=orange!50!yellow,
    rounded corners=5pt,
    ultra thick,
    inner color=orange!75!yellow!10,
    outer color=orange!75!yellow!25,
    font=\sffamily,
    text height=2ex,
    text depth=.5ex,
  },
  /tikz/my pins/.style={font=\sffamily\footnotesize, text height=1ex, text depth=.25ex, inner sep=1pt},
  right pin/.style args={#1:#2}{%
    tikz+={%
      \scoped[on background layer]\draw [thick, draw=orange!50!yellow, shorten <=-5pt] () -- ++(#1:35pt) node [right, my pins] {‘#2’};
    }
  },
  right pins/.style={%
    split={#1}{,}{right pin}
  },
  left pin/.style args={#1:#2}{%
    tikz+={%
      \scoped[on background layer]\draw [thick, draw=orange!50!yellow, shorten <=-5pt] () -- ++(#1:35pt) node [my pins, left] {‘#2’};
    }
  },
  left pins/.style={%
    split={#1}{,}{left pin}
  },
  [Animal, right pins={40:can move,20:eats,0:reproduces}
    [Bird, left pins={-160:lays eggs,180:is warm-blooded,160:has feathers}
      [Canary, left pins={-170:is small,170:works in coal mines}
      ]
      [Ostrich, right pins={-10:cannot fly,10:is quite large}
      ]
    ]
    [Fish, right pins={-10:has gills,10:can swim}
    ]
    [Mammal, right pins={-15:has fur,5:produces milk,25:bears live young,45:breathes air}
      [Dog, left pins={170:barks,-170:wags tail}
        [Chihuahua, left pins={-170:is teeny,170:is fierce}
        ]
        [Dalmation, right pins={-10:has 100 siblings,10:is spotted}
          [Fido, right pins={-10:has red kennel,10:is scared of mice}
          ]
        ]
      ]
      [Dolphin, right pins={-10:is highly social,10:lives in pods}
      ]
    ]
  ]
\end{forest}
\end{document}
| improve this answer | |
  • This is a usefully and great solution, tanks a lot. The explanation is also great. I need to make some minor changes, because i use Context. Now, with this approach, is very easy for me to make all the diagrams that i need to do. Thanks again and have a nice day. – Jorge Apr 19 '16 at 10:16
  • I'm glad it is useful! I wasn't sure because I don't know ConTeXt and I feared it might not be usable. I'm pleased to hear that's not the case :). – cfr Apr 19 '16 at 11:53
2

After cfr suggestion I post my own code because Tikz/forest don't works in ConteXt. The function pins(box name)(left "e" or right "d")("characteristic one","characteristic two", ...) do the job.

\startMPdefinitions
input boxes;
\stopMPdefinitions


\starttext


\startMPcode

% best guess at the required colors
color mid_blue, dark_blue, laranja, dentro, fora;
mid_blue  = (79/255, 129/255, 189/255); 
dark_blue = (56/255,  93/255, 138/255);
laranja=(1,0.6,0);
dentro = .75*laranja + .10*yellow;
fora = .75*laranja + .25*yellow;

%% boxes names
boxit.animal    ("Animal");
boxit.fish        ("Peixe");
boxit.bird       ("Ave");
boxit.mammal   ("Mamífero");
boxit.canary("Canário");
boxit.ostrich("Avestruz");
boxit.dog("Cão");
boxit.dolphin("Golfinho");
boxit.chi("Chihuahua");
boxit.dal("Dálmata");
boxit.fido("Aika");


%% boxes positions

fish.c = origin; 
fish.c = animal.c - 40 up;
animal.c = .5[bird.c,mammal.c] + 40 up; 
bird.c - fish.c= fish.c - mammal.c = 130 left;  
ostrich.c = bird.c + 40 down;
canary.c = ostrich.c + 70 left;
dolphin.c = mammal.c + 30 right + 40 down;
dog.c = dolphin.c + 75 left;
chi.c = dog.c + 60 left + 40 down;
dal.c = dog.c + 60 right + 40 down;
fido.c = dal.c + 40 down;

forsuffixes x = animal, fish, mammal, bird, ostrich, canary, dog, dolphin, chi, dal, fido:
  x.ne-x.sw = (60,20); 

  fill bpath x withcolor fora;
  draw pic   x withcolor  \MPcolor{darkred};
  draw bpath x withcolor dentro;

endfor

%%% arrows and paths
path p[];
p1 = animal.sw -- bird.ne;
p2 = animal.s--fish.n;
p3 = animal.se -- mammal.nw;
p4 = bird.s--ostrich.n;
p5 = bird.s--canary.ne;
p6=mammal.s--dog.n;
p7=dog.s--chi.n;
p8=dog.s--dal.n;
p9=dal.s--fido.n;
p10=mammal.s--dolphin.n;

%%%%
def pins(suffix caixa)(expr local)(text thelabels) =
      pair pos[]; 
      string name[], sitio; 
      if local="d":
      pos1=caixa.e;
      pos2=caixa.se; pos3=caixa.ne;
      else:
      pos1=caixa.w;
      pos3=caixa.sw; pos2=caixa.nw;
      fi;

      path cami, lixo;
      cami := pos3 -- pos2;
      k:= 0; for t = thelabels: k := k+1; name[k] = t; endfor
      for i = 1 upto k:
          pos4 := (i/(k+1))[pos2,pos3];
          pos5 := pos4 if local="d": + else: - fi (20, i*2);
         label.if local="d": rt else: lft fi(textext(name[i]) scaled .5, pos5);
         draw pos4 -- pos5; 
      endfor;
enddef;


drawoptions(withpen pencircle scaled 1 pt withcolor mid_blue);
for i=1 upto 10:
draw p[i];
endfor 

pins(animal)("d")("Come","Move-se", "Reproduz-se");
pins(bird)("e")("tem asas","pode voar", "põe ovos");
pins(mammal)("d")("respira ar","produzem leite","têm pele");
pins(dolphin)("d")("vivem na água","têm barbatanas");
pins(dal)("d")("têm pontos negros","máscote dos bombeiros");
pins(fido)("d")("animal de estimação","gosta de doces");
pins(chi)("e")("é castanho","é pequeno");
pins(dog)("e")("tem pelo","têm cauda");
pins(canary)("e")("é amarelo","canta");
pins(ostrich)("d")("não voa","é grande");
pins(fish)("e")("vive na água","têm cauda");

\stopMPcode


\stoptext

the output:

enter image description here Thanks to all

| 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.