6

I use the forest package to create a diagram similar to the one below. Is there any chance to reduce the distance between B5 and B6? I would prefer, if B6 and its subtree could be moved up. I have played around with the options l, s, l sep, s sep and fit without success so far. Actually I thought the default value fit=tight should do the job, but it does not...

enter image description here

Source for example diagram:

\documentclass{standalone}
\usepackage{forest}

\begin{document}
\begin{forest}
for tree={fit=tight}
[A, grow'=east
[B1,
[B2,
[B3,
[B4,
[B5,
[B6, grow'=east,
[C, grow'=east,
[D1, for tree={grow=north},
[D2,
[D3
]]]
[E1, for tree={grow=south},
[E2
]]]]]]]]]]
\end{forest}
\end{document}

Source for full diagram:

\documentclass{standalone}
\usepackage{forest}

% Document
\begin{document}
\begin{forest}
for tree={anchor=center}
[FB, grow'=east
[BJ$_X$
[BJ$_Y$
[BJ$_Z$
[BJ$_X$
[BJ$_Y$
[BJ$_Z$, grow'=east
[F, grow'=east
[LLJ$_X$, for tree={grow=north}
[LLJ$_Z$
[F, grow=east
[FT, for tree={grow=south}, [WMJ$_{ABD}$, [WM$_{ABD}$]]]
[ABD, for tree={grow=north}
[ULJ$_X$
[ULJ$_Y$
[ULJ$_Z$
[F, grow=east
[FT, for tree={grow=south}, [WMJ$_{THO}$, [WM$_{THO}$]]]
[THO, for tree={grow=north}
[F, grow'=east
[F, grow'=east
[LNJ$_X$, [LNJ$_Y$, [LNJ$_Z$, [HEA, for tree={grow=north}, [EP]]]]]
[SJ$_{L,X}$, for tree={grow=south}, [SJ$_{L,Y}$, [SJ$_{L,Z}$, [UPA$_L$, [EJ$_{L,Z}$, [LOA$_L$, [EP]]]]]]]
]
[SJ$_{R,X}$, for tree={grow=south}, [SJ$_{R,Y}$, [SJ$_{R,Z}$, [UPA$_R$, [EJ$_{R,Z}$, [LOA$_R$, [EP]]]]]]]
]]]]]]]]]]
[PEL, for tree={grow=south}
[F, grow=south
[HJ$_{L,X}$, [HJ$_{L,Y}$, [HJ$_{L,Z}$, [THI$_L$, [KJ$_{L,Z}$, [SHA$_L$, [AJ$_{L,X}$, [AJ$_{L,X}$, [AJ$_{L,X}$, [F, grow'=east, [COPJ$_{L,X}$, for tree={grow=north}, [COPJ$_{L,Y}$, [COPJ$_{L,Z}$, [COP$_L$]]]], [FOO$_L$, [EP]]]]]]]]]]]]
[HJ$_{R,X}$, [HJ$_{R,Y}$, [HJ$_{R,Z}$,, [THI$_R$, [KJ$_{R,Z}$, [SHA$_R$, [AJ$_{R,X}$, [AJ$_{R,X}$, [AJ$_{R,X}$, [F, grow'=east, [COPJ$_{R,X}$, for tree={grow=north}, [COPJ$_{R,Y}$, [COPJ$_{R,Z}$, [COP$_R$]]]], [FOO$_R$, [EP]]]]]]]]]]]]
]]]]]]]]]]
\end{forest}
\end{document}
  • 1
    Does for tree={fit=tight,l sep=-30mm} help? – Bobyandbob Apr 22 '17 at 13:48
  • Using l sep=-30mm, will reduce the longest line between B5 and B6, but it won't reduce the other lines any further ... at least not in my tests. – Tina Apr 22 '17 at 13:58
  • Thank you for your quick responses. l sep=-30mm works fine for the given example. Unfortunately not for my actual diagram (I added the source to the question). So probably I have to play around with l sep for each node? – JotWe Apr 22 '17 at 14:15
  • You can increase it to l sep=-200mm... Maybe it creates other line problems. But do you really need such big diagram? I – Bobyandbob Apr 22 '17 at 14:32
  • Well, I was able to tune the distances by setting l sep+=5mm for the F nodes and l sep=-300mm for the others. Thank you again! If you put your comment in an answer, I am happy to accept it :) – JotWe Apr 22 '17 at 14:48
5

To be honest, I'm not sure this is much of an improvement. However, it is a lot clearer what is going on and the code is considerably less cluttered. It is also slightly more compact (both width and height/depth are smaller than in the OP's solution). Whether any of this is of any importance is, of course, another matter.

\documentclass[border=10pt]{standalone}
\usepackage{forest}
\usetikzlibrary{matrix}
\tikzset{
  fixedBase/.style={draw, circle, fill=black, text=white},
  prismaticJoint/.style={draw},
  revoluteJoint/.style={draw, rounded corners=2mm},
  rigidLink/.style={draw, color=blue, fill=blue, text=white},
  fixedTranslation/.style={draw, fill=gray},
  fixedRotation/.style={draw, fill=gray, rounded corners=2mm},
  springDamperElement/.style={draw, circle, color=blue, fill=blue, text=white},
  fork/.style={draw, circle, color=red, fill=red, text=white},
  endpoint/.style={draw, fill=black, text=white},
}
\newsavebox\treelegend
\setbox0=\hbox{% solution from Steven B. Segletes: https://tex.stackexchange.com/a/366710/
  \begin{tikzpicture}
    \matrix [matrix of nodes, column 2/.style={text height=3.5mm, text depth=3.5mm, text width=40mm}]
    {%
      |[fixedBase]| F8 & Fixed base \\
      |[prismaticJoint]| PJ & Prismatic joint \\
      |[revoluteJoint]| RJ & Revolute joint \\
      |[rigidLink]| RL & Rigid link \\
      |[fixedTranslation]| FT & Fixed translation \\
      |[springDamperElement]| SD & Spring-damper element \\
      |[fork]| F & Fork \\
      |[endpoint]| EP & Endpoint \\
    };
  \end{tikzpicture}%
}
\savebox\treelegend{\copy0}
\begin{document}
\begin{forest} 
  fork/.style={
    /tikz/fork,
    before computing xy={for children={l'+=8mm}},
  },
  for tree={
    anchor=center
  },
  before computing xy={
    for tree={l'=9mm},
  }
  [FB, fixedBase, grow'=east, anchor=east
    [BJ$_X$, prismaticJoint, for tree={grow=north}
    [BJ$_Y$, prismaticJoint
    [BJ$_Z$, prismaticJoint
    [BJ$_X$, revoluteJoint
    [BJ$_Y$, revoluteJoint
    [BJ$_Z$, revoluteJoint, grow'=east
    [F, fork, grow'=east, before computing xy={for children={l'+=5mm}}
    [LLJ$_X$, revoluteJoint, for tree={grow=north}
            [LLJ$_Z$, revoluteJoint
            [F, fork, grow=east
            [FT, fixedTranslation, for tree={grow=south}
              [WMJ$_{ABD}$, prismaticJoint
                [SD, springDamperElement, before computing xy={l'=0pt, s'=15mm}]
                [EP, endpoint, before computing xy={l=10mm, s'=0pt}]
              ]
            ]
            [ABD, rigidLink, for tree={grow=north}
            [ULJ$_X$, revoluteJoint
            [ULJ$_Y$, revoluteJoint
            [ULJ$_Z$, revoluteJoint
            [F, fork, grow=east
            [FT, fixedTranslation, for tree={grow=south}
              [WMJ$_{THO}$, prismaticJoint
                [SD, springDamperElement, before computing xy={l'=0pt, s'=15mm}]
                [EP, endpoint, before computing xy={l=10mm, s'=0pt}]
              ]
            ]
            [THO, rigidLink, for tree={grow=north}
            [F, fork, grow'=east, before computing xy={for children={l'+=10mm}}
            [F, fork, grow'=east
            [LNJ$_X$, revoluteJoint
              [LNJ$_Y$, revoluteJoint
                [LNJ$_Z$, revoluteJoint
                  [HEA, rigidLink, for tree={grow=north}
                    [EP, endpoint]
                  ]
                ]
              ]
            ]
            [SJ$_{L,X}$, revoluteJoint, for tree={grow=south}
              [SJ$_{L,Y}$, revoluteJoint
                [SJ$_{L,Z}$, revoluteJoint
                  [UPA$_L$, rigidLink
                    [EJ$_{L,Z}$, revoluteJoint
                      [LOA$_L$, rigidLink
                        [EP, endpoint]
                      ]
                    ]
                  ]
                ]
              ]
            ]
          ]
          [SJ$_{R,X}$, revoluteJoint, for tree={grow=south}
            [SJ$_{R,Y}$, revoluteJoint
              [SJ$_{R,Z}$, revoluteJoint
                [UPA$_R$, rigidLink
                  [EJ$_{R,Z}$, revoluteJoint
                    [LOA$_R$, rigidLink
                      [EP, endpoint]
                    ]
                   ]
                 ]
               ]
             ]
           ]
    ]]]]]]]]]
    ]
    [PEL, rigidLink, for tree={grow=south}
      [F, fork, grow=south, before packing={s sep'+=5mm}, before computing xy={for children={l'-=5mm}}
        [HJ$_{L,X}$, revoluteJoint
          [HJ$_{L,Y}$, revoluteJoint
            [HJ$_{L,Z}$, revoluteJoint
              [THI$_L$, rigidLink
                [KJ$_{L,Z}$, revoluteJoint
                  [SHA$_L$, rigidLink
                    [AJ$_{L,X}$, revoluteJoint
                      [AJ$_{L,Y}$, revoluteJoint
                        [AJ$_{L,Z}$, revoluteJoint
                          [F, fork, grow'=east
                            [COPJ$_{L,X}$, prismaticJoint, for tree={grow=north}
                              [COPJ$_{L,Y}$, prismaticJoint
                                [COPJ$_{L,Z}$, prismaticJoint
                                  [EP, endpoint]
                                ]
                              ]
                            ]
                            [FOO$_L$, rigidLink
                              [EP, endpoint]
                            ]
                          ]
                        ]
                      ]
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
        [HJ$_{R,X}$, revoluteJoint
          [HJ$_{R,Y}$, revoluteJoint
            [HJ$_{R,Z}$, revoluteJoint
              [THI$_R$, rigidLink
                [KJ$_{R,Z}$, revoluteJoint
                  [SHA$_R$, rigidLink
                    [AJ$_{R,X}$, revoluteJoint
                      [AJ$_{R,Y}$, revoluteJoint
                        [AJ$_{R,Z}$, revoluteJoint
                          [F, fork, grow'=east
                            [COPJ$_{R,X}$, prismaticJoint, for tree={grow=north}
                              [COPJ$_{R,Y}$, prismaticJoint
                                [COPJ$_{R,Z}$, prismaticJoint
                                  [EP, endpoint]
                                ]
                              ]
                            ]
                            [FOO$_R$, rigidLink
                              [EP, endpoint]
                            ]
                          ]
                        ]
                      ]
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ]
    ]]]]]]]]
  ]
  \node [anchor=north west] at (current bounding box.north west) {\usebox{\treelegend}};
\end{forest}
\end{document}

which-way tree

| improve this answer | |
  • @JotWe I've also left a message in the Forest chat room as I'm not clear whether it is expected that this much manual intervention is needed i.e. that Forest gets confused very quickly. But I think Forest's author is not around just at the moment. – cfr Apr 26 '17 at 19:48
3

Ok, thank you Bobyandbob and Tina for providing the initial hint. The option l sep was the key. Here is the code and diagram I finally came up with. I had to use some before computing xy, but I like the result.

enter image description here

\documentclass{standalone}
\usepackage{forest}

\begin{document}
\forestset{
fixedBase/.style={draw, circle, fill=black, text=white},
prismaticJoint/.style={draw},
revoluteJoint/.style={draw, rounded corners=2mm},
rigidLink/.style={draw, color=blue, fill=blue, text=white},
fixedTranslation/.style={draw, fill=gray},
fixedRotation/.style={draw, fill=gray, rounded corners=2mm},
springDamperElement/.style={draw, circle, color=blue, fill=blue, text=white},
fork/.style={draw, circle, color=red, fill=red, text=white},
endpoint/.style={draw, fill=black, text=white},
}

\begin{forest}
for tree={anchor=center}
[FB, fixedBase, l sep=-300mm, grow'=east,
[FB, fixedBase, edge'={}, grow'=east, before computing xy={l=5mm, s=160mm}, [Fixed base, edge'={}, anchor=west, before computing xy={l=5mm, s=0}]],
[PJ, prismaticJoint, edge'={}, grow'=east, before computing xy={l=5mm, s=150mm}, [Prismatic joint, edge'={}, anchor=west, before computing xy={l=5mm, s=0}]],
[RJ, revoluteJoint, edge'={}, grow'=east, before computing xy={l=5mm, s=140mm}, [Revolute joint, edge'={}, anchor=west, before computing xy={l=5mm, s=0}]],
[RL, rigidLink, edge'={}, grow'=east, before computing xy={l=5mm, s=130mm}, [Rigid link, edge'={}, anchor=west, before computing xy={l=5mm, s=0}]],
[FT, fixedTranslation, edge'={}, grow'=east, before computing xy={l=5mm, s=120mm}, [Fixed translation, edge'={}, anchor=west, before computing xy={l=5mm, s=0}]],
[SD, springDamperElement, edge'={}, grow'=east, before computing xy={l=5mm, s=110mm}, [Spring-damper element, edge'={}, anchor=west, before computing xy={l=5mm, s=0}]],
[F, fork, edge'={}, grow'=east, before computing xy={l=5mm, s=100mm}, [Fork, edge'={}, anchor=west, before computing xy={l=5mm, s=0}]],
[EP, endpoint, edge'={}, grow'=east, before computing xy={l=5mm, s=90mm}, [Endpoint, edge'={}, anchor=west, before computing xy={l=5mm, s=0}]],
[BJ$_X$, prismaticJoint, l sep=-300mm, for tree={grow=north}, before computing xy={l=12mm, s=0}, 
[BJ$_Y$, prismaticJoint, l sep=-300mm, 
[BJ$_Z$, prismaticJoint, l sep=-300mm, 
[BJ$_X$, revoluteJoint, l sep=-300mm, 
[BJ$_Y$, revoluteJoint, l sep=-300mm, 
[BJ$_Z$, revoluteJoint, l sep=-300mm, grow'=east,
[F, fork, grow'=east,
[LLJ$_X$, revoluteJoint, l sep=-300mm, for tree={grow=north},
[LLJ$_Z$, revoluteJoint, l sep=-300mm,
[F, fork, grow=east,
[FT, fixedTranslation, for tree={grow=south}, [WMJ$_{ABD}$, prismaticJoint, [SD, springDamperElement, before computing xy={l=0, s=15mm}], [EP, endpoint, before computing xy={l=10mm, s=0}]]],
[ABD, rigidLink, l sep=-300mm, for tree={grow=north},
[ULJ$_X$, revoluteJoint, l sep=-300mm,
[ULJ$_Y$, revoluteJoint, l sep=-300mm,
[ULJ$_Z$, revoluteJoint, l sep=-300mm,
[F, fork, grow=east,
[FT, fixedTranslation, for tree={grow=south}, [WMJ$_{THO}$, prismaticJoint, [SD, springDamperElement, before computing xy={l=0, s=15mm}], [EP, endpoint, before computing xy={l=10mm, s=0}]]],
[THO, rigidLink, l sep=-300mm, for tree={grow=north},
[F, fork, l sep+=15mm, grow'=east,
[F, fork, l sep+=5mm, grow'=east,
[LNJ$_X$, revoluteJoint, [LNJ$_Y$, revoluteJoint, [LNJ$_Z$, revoluteJoint, [HEA, rigidLink, for tree={grow=north}, [EP, endpoint]]]]],
[SJ$_{L,X}$, revoluteJoint, for tree={grow=south}, [SJ$_{L,Y}$, revoluteJoint, [SJ$_{L,Z}$, revoluteJoint, [UPA$_L$, rigidLink, [EJ$_{L,Z}$, revoluteJoint, [LOA$_L$, rigidLink, [EP, endpoint]]]]]]],
],
[SJ$_{R,X}$, revoluteJoint, for tree={grow=south}, [SJ$_{R,Y}$, revoluteJoint, [SJ$_{R,Z}$, revoluteJoint, [UPA$_R$, rigidLink, [EJ$_{R,Z}$, revoluteJoint, [LOA$_R$, rigidLink, [EP, endpoint]]]]]]],
]]]]]]]]]],
[PEL, rigidLink, for tree={grow=south},
[F, fork, grow=south,
[HJ$_{L,X}$, revoluteJoint, l sep=-300mm, [HJ$_{L,Y}$, revoluteJoint, l sep=-300mm, [HJ$_{L,Z}$, revoluteJoint, l sep=-300mm, [THI$_L$, rigidLink, l sep=-300mm, [KJ$_{L,Z}$, revoluteJoint, l sep=-300mm, [SHA$_L$, rigidLink, l sep=-300mm, [AJ$_{L,X}$, revoluteJoint, l sep=-300mm, [AJ$_{L,Y}$, revoluteJoint, l sep=-300mm, [AJ$_{L,Z}$, revoluteJoint, l sep=-300mm, [F, fork, grow'=east, [COPJ$_{L,X}$, prismaticJoint, for tree={grow=north}, [COPJ$_{L,Y}$, prismaticJoint, [COPJ$_{L,Z}$, prismaticJoint, [EP, endpoint]]]], [FOO$_L$, rigidLink, [EP, endpoint]]]]]]]]]]]],
[HJ$_{R,X}$, revoluteJoint, l sep=-300mm, [HJ$_{R,Y}$, revoluteJoint, l sep=-300mm, [HJ$_{R,Z}$, revoluteJoint, l sep=-300mm, [THI$_R$, rigidLink, l sep=-300mm, [KJ$_{R,Z}$, revoluteJoint, l sep=-300mm, [SHA$_R$, rigidLink, l sep=-300mm, [AJ$_{R,X}$, revoluteJoint, l sep=-300mm, [AJ$_{R,Y}$, revoluteJoint, l sep=-300mm, [AJ$_{R,Z}$, revoluteJoint, l sep=-300mm, [F, fork, grow'=east, [COPJ$_{R,X}$, prismaticJoint, for tree={grow=north}, [COPJ$_{R,Y}$, prismaticJoint, [COPJ$_{R,Z}$, prismaticJoint, [EP, endpoint]]]], [FOO$_R$, rigidLink, [EP, endpoint]]]]]]]]]]]],
]]]]]]]]]]
\end{forest}
\end{document}
| improve this answer | |
  • I think you could prune this quite a bit. l sep=-300mm doesn't make much sense. I would rename fork, if I were you, to avoid confusion with forked edge. I mean, technically, fork is fine. But I would find it potentially confusing. – cfr Apr 22 '17 at 19:10
  • Thanks for the comment. I agree with you that it might be confusing, but these are predefined terms from a modeling library I used. – JotWe Apr 23 '17 at 9:26
  • I was more concerned about l sep=-300mm. Since l sep is the minimum separation permitted between levels, what would this mean? That the next level always precede its parent by at least 0.3m? – cfr Apr 23 '17 at 22:05
  • 1
    Yes, the approach is quite 'hacky' and probably just tricks the placing algorithm. Do you think there is a better solution? – JotWe Apr 24 '17 at 7:55
  • 1
    When I implemented the graph, it was very convenient to use the syntax of the forest package in order to get the general form. In a second step I started to care about the look and placed some of the nodes manually to make it more compact. The legend is definitely a pretty dirty hack, but because I use it as a standalone figure, compilation time is not that important. – JotWe Apr 25 '17 at 19:15

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.