4

I applied the following code to draw a feature diagram, however, I do not want all child nodes to be concrete, as this code shows In particular, I need to specify some of the child node to be abstract

How can I do that? And also, how can I make disjunct branches (unfilled angle) (e.t. as not all the child nodes are alternatives in my case)?

I took the code form this post

\documentclass[border=10pt,tikz,multi]{standalone}
\usetikzlibrary{angles,shadows.blur,positioning,backgrounds}
\usepackage{forest}
\forestset{
  declare count register=disjuncts from,
  disjuncts from'=0,
  declare count register=concrete from,
  concrete from'=2,
  concrete colour/.code={\colorlet{concretecol}{#1}},
  abstract colour/.code={\colorlet{abstractcol}{#1}},
  draw colour/.code={\colorlet{drawcol}{#1}},
  concrete colour=gray,
  abstract colour=white,
  draw colour=black,
  /tikz/mandatory/.style={circle, fill=drawcol, draw=drawcol},
  /tikz/optional/.style={circle, draw=drawcol, fill=white},
  /tikz/concrete/.style={fill=concretecol, draw=drawcol},
  /tikz/abstract/.style={fill=abstractcol, draw=drawcol},
  /tikz/or/.style={},
  mandatory/.style={edge label={node [mandatory] {}}},
  optional/.style={edge label={node [optional] {}}},
  or/.style={for first={disjunct}},
  disjunct/.style={
    tikz+={\path (.parent) coordinate (A) -- (!u.children) coordinate (B) -- (!ul.parent) coordinate (C) pic [fill=drawcol] {angle};}
  },
  disjunction tree/.style={
    where={isodd(n_children())}{
      for n={int((n_children()+1)/2)}{calign with current},
    }{
      calign=midpoint,
    },
    before typesetting nodes={
      for nodewalk={
        filter/.wrap pgfmath arg={{level>=##1}{n_children()>1}}{(disjuncts_from)}
      }{
        or,
      },
      where={level()>=(concrete_from)}{
        concrete,
      }{
        abstract,
      },
      tikz+={
        [font=\sffamily]
        \node (l) [anchor=north west, xshift=10pt] at (current bounding box.north east) {Legend};
        \foreach \i/\j [remember=\i as \k (initially l)] in {mandatory/Mandatory,optional/Optional,or/Or,abstract/Abstract,concrete/Concrete}
        {
          \node (\i) [below=20pt of \k.north, anchor=north, text centered, \i, minimum width=5pt,] {};
          \node (\j) [right=15pt of \i.center -| mandatory.west, anchor=west] {\j};
        };
        \draw [drawcol] (or.south west) coordinate (A) -- (or.north) coordinate (B) -- (or.south east) coordinate (C) pic [fill=drawcol, angle radius=5pt] {angle};
        \foreach \i in {mandatory,optional} \draw [darkgray] (\i.north east) -- +(45:5pt);
        \node (c) [below=0pt of Concrete.south] {};
        \scoped[on background layer]{\node [draw, fill=white, blur shadow, fit=(l) (Mandatory) (Optional) (Or) (Abstract) (Concrete) (c), rounded corners] {};}
      },
    },
    for tree={
      parent anchor=children,
      child anchor=parent,
      l'+=10mm,
      blur shadow,
      rounded corners,
      text height=2ex,
      text depth=.5ex,
      font=\sffamily,
    },
  },
}
\begin{document}
\begin{forest}% addaswyd o gôd Salim Bou: https://tex.stackexchange.com/a/335782/
  disjunction tree,
  disjuncts from'=1,
  concrete from'=1,
  concrete colour=blue!85!cyan!40,
  abstract colour=blue!85!cyan!15,
  draw colour=darkgray,
  [Emergency Response System
    [User interface, mandatory]
    [Inform emergency,  mandatory
      [Inform Earthquake, abstract colour=blue!85!cyan!15]
      [Inform flood]
    ]
    [Display neighbourhood, mandatory
      [Map
        [Display danger zone]
        [Display safe zone]
        [Display path to safe zone]
      ]
      [Textual direction]
    ]
    [Shortcut calls, optional
      [Cops]
      [Ambulance]
      [Fireman]
    ]
  ]
\end{forest}
\end{document}

enter image description here

Also, How can I add an angle filled with white color and also add it to legend and named as (Alternative) as in this diagram enter image description here

4

I'm not familiar with forest, so just take this as an attempt:

  • To mark a child node as abstract, just add option abstract to that node, for example [Display danger zone, abstract].

    Corresponding code changes: the block

    where={level()>=(concrete_from)}{
      concrete,
    }{
      abstract,
    },
    

    are moved from inside before typesetting nodes={...} to inside for tree={...}.

  • Now the or angles are only drawn without filling by default. You can use or={list of <start/end> pairs} to specify the filled (sub)angles. For example or={1/l} means fill the (sub)angle from the 1st child node to the last, and or={1/2, 4/5} means fill the (sub)angles from 1st to 2nd, and 4th to 5th, respectively.

    Corresponding code changes: Definition of style disjunct is adjusted.

\documentclass[border=10pt,tikz,multi]{standalone}
\usetikzlibrary{angles,shadows.blur,positioning,backgrounds}
\usepackage{forest}
\forestset{
  declare count register=disjuncts from,
  disjuncts from'=1,
  declare count register=concrete from,
  concrete from'=1,
  concrete colour/.code={\colorlet{concretecol}{#1}},
  abstract colour/.code={\colorlet{abstractcol}{#1}},
  draw colour/.code={\colorlet{drawcol}{#1}},
  concrete colour=blue!85!cyan!40,
  abstract colour=blue!85!cyan!15,
  draw colour=darkgray,
  /tikz/mandatory/.style={circle, fill=drawcol, draw=drawcol},
  /tikz/optional/.style={circle, draw=drawcol, fill=white},
  /tikz/concrete/.style={fill=concretecol, draw=drawcol},
  /tikz/abstract/.style={fill=abstractcol, draw=drawcol},
  /tikz/or/.style={},
  mandatory/.style={edge label={node [mandatory] {}}},
  optional/.style={edge label={node [optional] {}}},
  or/.style={for first={disjunct={#1}}},
  disjunct/.style={
    tikz+={
      \path (.parent) coordinate (A) -- (!u.children) coordinate (B) -- (!ul.parent) coordinate (C) pic {angle};
      \foreach \i/\j in {#1} {
        \path (!u\i.parent) coordinate (A) -- (!u.children) coordinate (B) -- (!u\j.parent) coordinate (C) pic [fill=drawcol] {angle};
      }
    }
  },
  disjunction tree/.style={
    where={isodd(n_children())}{
      for n={int((n_children()+1)/2)}{calign with current},
    }{
      calign=midpoint,
    },
    before typesetting nodes={
      for nodewalk={
        filter/.wrap pgfmath arg=
          {{level>=##1}{n_children()>1}}{(disjuncts_from)}
      }{
        or
      },
%      where={level()>=(concrete_from)}{
%        concrete,
%      }{
%        abstract,
%      },
      tikz+={
        [font=\sffamily]
        \node (l) [anchor=north west, xshift=10pt] at (current bounding box.north east) {Legend};
        \foreach \i/\j [remember=\i as \k (initially l)] in {mandatory/Mandatory,optional/Optional,or/Or,abstract/Abstract,concrete/Concrete}
        {
          \node (\i) [below=20pt of \k.north, anchor=north, text centered, \i, minimum width=5pt,] {};
          \node (\j) [right=15pt of \i.center -| mandatory.west, anchor=west] {\j};
        };
        \draw [drawcol] (or.south west) coordinate (A) -- (or.north) coordinate (B) -- (or.south east) coordinate (C) pic [fill=drawcol, angle radius=5pt] {angle};
        \foreach \i in {mandatory,optional} \draw [darkgray] (\i.north east) -- +(45:5pt);
        \node (c) [below=0pt of Concrete.south] {};
        \scoped[on background layer]{\node [draw, fill=white, blur shadow, fit=(l) (Mandatory) (Optional) (Or) (Abstract) (Concrete) (c), rounded corners] {};}
      },
    },
    for tree={
      parent anchor=children,
      child anchor=parent,
      l'+=10mm,
      blur shadow,
      rounded corners,
      text height=2ex,
      text depth=.5ex,
      font=\sffamily,
      where={level()>=concrete_from()}{
        concrete,
      }{
        abstract,
      },
    },
  },
}
\begin{document}
\begin{forest}% addaswyd o gôd Salim Bou: https://tex.stackexchange.com/a/335782/
  disjunction tree,
  [Emergency Response System
    [User interface, mandatory]
    [Inform emergency, mandatory,for children={abstract}
      [Inform Earthquake]
      [Inform flood]
    ]
    [Display neighbourhood, mandatory,or={1/l} % 1 (the first) to ell (the last)
      [Map,or={2/3}
        [Display danger zone,abstract]
        [Display safe zone]
        [Display path to safe zone]
      ]
      [Textual direction]
    ]
    [Shortcut calls, optional,or={1/2,4/5}
      [Cops]
      [Ambulance]
      [Fireman,abstract]
      [Node]
      [Node]
    ]
  ]
\end{forest}
\end{document}

enter image description here

5
  • 1
    Excuse me for my edit adding the image. +1
    – Sebastiano
    Jun 17 at 19:55
  • 2
    @Sebastiano That's always welcome, and thank you for adding it. Jun 17 at 20:03
  • Thank you for your help
    – user36877
    Jun 18 at 14:59
  • @muzimuzhiZ Thank you for your help How I can add an angle filled with white color and also add it to legend and named as (Alternative) as in this diagram link
    – user36877
    Jun 18 at 15:14
  • Are there any rules about where the abstract nodes will appear? Do they always appear at the beginning of the list of children nodes? Jun 19 at 10:54

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.