0

I am trying to create a few simple macros for B-Trees and one of these macros is supposed to create a multipart node tikz based on the number of arguments it gets. Therefore I used the g argument specifier from xparse though tikz always shows the following error:

Package tikz Error: Giving up on this path. Did you forget a semicolon?. ;
Package tikz Error: Giving up on this path. Did you forget a semicolon?. ;
Undefined control sequence. ;

The macro works flawlessly when replacing the gs with ms though then it becomes impossible to differentiate between a multipart node with e.g. 4 segments two of which are empty and an 2 segment node which are all filled.

A kinda minimal working example:

\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\usetikzlibrary{trees,shapes.multipart}

\NewDocumentCommand\test{m g}{
  {#1 \IfValueT{#2}{B}}
}
\NewDocumentCommand\leaf{m m}{
  node[leaf]{#1 \nodepart{two} #2}
}
\NewDocumentCommand\leafOptional{m g}{
  node[leaf]{#1 \IfValueT{#2}{\nodepart{two} #2}}
}


\tikzset{
  btree/.style={
    nodes={rectangle split,rectangle split horizontal=true,draw},
    leaf/.style={
      rectangle split allocate boxes=2,
      rectangle split parts=2,
      rectangle split part fill=white}
  },
}

\begin{document}
\test{a}\\ % this works
\test{a}{something}\\ % as does this
\begin{tikzpicture}[btree]
\node (root) {test}
  child {\leaf{5}{}}
  child {\leafOptional{5}} % however this fails
  child {\leafOptional{5}{}} % and so does this
  child {node[leaf]{1}}
;
\end{tikzpicture}
\end{document}

I already found this question TikZ path doesn't work with xparse generated macro which seems to be a similar problem though I am unable to use \DeclareDocumentCommand as it does not allow one to use the g/G argument specifier

Addedum

Following @PhelypeOleinik's comment I changed the code to use \NewExpandableDocumentCommand and the argument specifier o o o m however when passing more than one optional argument this leads to tikz not determining the correct node bounding box and tikz draws the edge into the actual node shape.

tikz drawing into the multipart node

\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\usetikzlibrary{trees,shapes.multipart}

\NewExpandableDocumentCommand\leaf{o o o m}{
  node[leaf]{
    6\nodepart{two}8\nodepart{three}2\nodepart{four}#4
  }
}


\tikzset{
  btree/.style={
    nodes={rectangle split,rectangle split horizontal=true,draw},
    level 1/.style={sibling distance=\textwidth/4},
    leaf/.style={rectangle split allocate boxes=4}
  },
}

\begin{document}
\begin{tikzpicture}[btree]
\node (root) {test}
  child {\leaf{5}}
  child {\leaf[a]{5}}
  child {\leaf[a][b]{5}}
  child {\leaf[a][b][c]{5}}
;
\end{tikzpicture}
\end{document}

Adding leaf/.style={..., rectangle split part fill=white} seems to fix the symptoms though not the root cause - any possibile solution to use this with transparent nodes?

4
  • really best to avoid g Jun 5, 2020 at 16:58
  • Don't use g: it's deprecated and it's bad practice. Apparently commands there need to be expandable, so you can use \NewExpandableDocumentCommand\leafOptional{o m}{node[leaf]{#2 \IfValueT{#1}{\nodepart{two} #1}}} and then use \leafOptional{5} or \leafOptional[opt]{5} Jun 5, 2020 at 17:00
  • @PhelypeOleinik okay it just seemed convenient to use only curly bracket. I tried using o m and it worked for one and two part nodes though o o m and more optional arguments seemed to lead to tikz not correctly recognizing the resulting box in drawing the edge into the center of the node overlaying it.
    – Septatrix
    Jun 6, 2020 at 7:11
  • Using macros in TikZ paths isn't that straight-forward. They need to be fully expandable. What is your preferred Input-Syntax and what should it do? Nov 6, 2022 at 1:35

1 Answer 1

0

I find using node[leaf] {\leaf ...} works:

\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\usetikzlibrary{trees,shapes.multipart}

\NewExpandableDocumentCommand\leaf{o o o m}{
    6\nodepart{two}8\nodepart{three}2\nodepart{four}#4
}

\tikzset{
  btree/.style={
    nodes={rectangle split,rectangle split horizontal=true,draw},
    level 1/.style={sibling distance=\textwidth/4},
    leaf/.style={rectangle split allocate boxes=4}
  }
}

\begin{document}
\begin{tikzpicture}[btree]
  \node (root) {test}
    child { node[leaf]{\leaf{5}} }
    child { node[leaf]{\leaf[a]{5}} }
    child { node[leaf]{\leaf[a][b]{5}} }
    child { node[leaf]{\leaf[a][b][c]{5}} }
  ;
\end{tikzpicture}

\end{document}

enter image description here

3
  • Yes that is also what my second code snippet does though I want to avoid filling the leafs as my plan is to superimpose this over another graphic/background
    – Septatrix
    Jun 17, 2020 at 17:51
  • @Septatrix I guess it is the not-fully-expandable command \nodepart that causes the original problem. Jun 17, 2020 at 21:49
  • It do not think so. All four rows calling my \leaf macro should expand to the same thing (a node with four parts) and the first two rows work as expected and only the later two do not. My guess it that it has to do with the additional optional arguments passed to the macro...
    – Septatrix
    Jun 18, 2020 at 8:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .