6

Long time reader, first time poster. I just can't seem to find a solution to this problem, so I defer to your expert advice! I initially tried to create a TiKzpicture inside of a node of a TiKzpicture, but then when I tried to draw edges between nodes within the inner TiKzpicture, I got the following error:

Undefined control sequence \path[->] (w0) edge[bend left=10] node[right] {$\R^{0}$} (v0);

(The error actually didn't fully display the line, no matter how I tried to coax TexStudio to tell me what the full error was, so I just copied the first offending line.)

I read this post (I don't have sufficient reputation to post links with appropriate formatting. Ugh!! How to avoid nesting of tikzpicture? ) One solution proposed was to create a lrbox which would contain the TiKzpicture, and then to use the command declared in the preamble of the document as follows:

\newsavebox\helloworld
...
\node [label={below:Hello World}] (hw) {\usebox\helloworld};

This actually solved the problem above, and the edges were successfully drawn between the desired nodes (e.g. (w0, v0) and (w1, v1). However, a new problem has arisen: I'm trying to draw an edge from a node within the TiKzpicture contained in the lrbox to a node in the "outer" TiKzpicture. From my understanding, the contents of the lrbox are rendered before the contents of the outer TiKzpicture; however, I'm not sure how else to approach this.

Here's from before I add the edge in, and then what happens after I add the edge:

Before adding the offending edge

Full view of broken edge

Here's my full code:

\documentclass{article}
\usepackage{float, latexsym, tikz, amssymb, amsmath, amsthm, graphicx, caption}

\usetikzlibrary{shapes,arrows,positioning,fit,matrix,calc}

\newsavebox\disjUn

\newcommand{\R}{\mathcal{R}}
\newcommand{\F}{\mathfrak{F}}

\begin{document}
    \tikzstyle{frame}=[draw,ellipse,minimum height=6cm,minimum width=2cm]
    \tikzstyle{world} =[draw,circle,fill=black, inner sep=0pt, minimum size=3pt]

    \begin{lrbox}{\disjUn}
    \begin{tikzpicture}[node distance=3cm]
        \node[frame] (F0){};
        \node at ([xshift=-1em, yshift=-4em]F0.north) [world, label={70:$(w,0)$}] (w0){}; 
        \node at ([yshift=3em]F0.south west) [world, label={-70:$(v,0)$}] (v0){};
        \path[->] (w0) edge[bend left=10] node[right] {$\R^{0}$} (v0);

        \node[frame, right of=F0] (F1){};
        \node at ([xshift=-1em, yshift=-4em]F1.north) [world, label={70:$(w,1)$}] (w1){}; 
        \node at ([yshift=3em]F1.south west) [world, label={-70:$(v,1)$}] (v1){};
        \path[->] (w1) edge[bend left=10] node[right] {$\R^{1}$} (v1);
    \end{tikzpicture}
    \end{lrbox}

    \begin{figure}[H]
    \centering
    \begin{tikzpicture}[remember picture, node distance=3cm, transform canvas={scale=0.9}]
    \node[draw=white, label={below:$\F \oplus \F$}] (FF) {\usebox\disjUn};

    \node[frame,right of=FF, xshift=3cm,label={below:$\F^{\prime}$}] (Fp){};
    \node at ([yshift=-4em]Fp.north) [world, label={70:$\hat{w}$}] (w){}; 
    \node at ([yshift=3em]Fp.south west) [world, label={-70:$\hat{v}$}] (v){};
    \node at ([yshift=3em]Fp.north east) [world, label={70:$w^{\prime}$}] (wp){};

    \path[->] (w) edge[bend left=10] node[right] {$\R^{\prime}$}(v);

    \path[-] (wp.west) edge[bend right,draw=gray, dashed] node [below]{} (Fp.north);
    \path[-] (wp.south east) edge[bend left,draw=gray, dashed] node [below]{} (Fp.north east);

    \path[->] (w0) edge[bend right, dashed] node[above] {$g$}(w);
    %\path[->] (w1) edge[bend right,dashed] node[above] {$g$}(wp);
    \end{tikzpicture}
    \end{figure}
\end{document}  

Are there any alternate solutions where I can nicely position the worlds within ellipses and have edges between these structures? Thanks so much in advance!

EDIT: I would also like to note that I am using the \disjUn TiKzpicture in a lrbox as a component of two TiKzpictures; I liked the fact that I could edit the diagram in only one place, and have the changes reflected in both diagrams! However, the fact that I cannot seem to draw edges to nor from nodes within this environment is problematic :(

A friend of mine recommended using \begin{scope}[...] \end{scope} to contain the different structures, but there's still the problem of code re-use, and positioning the worlds (the black dots) relative to the ovals... Thanks again for reading! :)

EDIT2: Thanks to AJN, I discovered that I had originally used the

remember picture

Argument in the wrong TiKz picture; it is meant to be on the inner TiKz picture; I suppose that this is because we want the compiler to remember the node names for use in the parent TiKz picture.

13
  • 3
    Welcome! That's not your full code. Please make it compilable. I don't really understand why you want to nest them. Why not just use a single picture environment?
    – cfr
    Mar 25, 2016 at 4:34
  • 1
    My apologies!! I thought it would be enough to give the full code for the figure, but you're totally right: it helps to be able to compile! Sorry about that :( Fixing now :)
    – Wanda B.
    Mar 25, 2016 at 4:43
  • Your example doesn't compile in my machine. What are the tikz libraries that you are using? frame, world etc do not seem to be defined.
    – AJN
    Mar 25, 2016 at 4:44
  • 1
    Have you compiled it twice? (the manual says that you might have to)
    – AJN
    Mar 25, 2016 at 12:35
  • 1
    @percusse The Tex.SE page that you linked to does not mention a reason for avoiding nesting. Is it just good practice or are there extra features that .pic would provide or does nesting break some features?
    – AJN
    Mar 25, 2016 at 12:38

2 Answers 2

3

I don't see why you need a separate box or a pic here. Since you are loading fit anyway, we can simply use that to contain the two nodes F0 and F1.

  \node (FF) [fit=(F0) (F1), draw=white, label={below:$\F \oplus \F$}] {};

Note that \tikzstyle is deprecated as is the <direction> of= syntax. arrows and shapes should be similarly replaced with their updated counterparts.

The first can be replaced with \tikzset:

\tikzset{% \tikzstyle is deprecated
  frame/.style={draw,ellipse,minimum height=6cm,minimum width=2cm},
  world/.style ={draw,circle,fill=black, inner sep=0pt, minimum size=3pt},
}

For the second, the positioning library's syntax is preferred and you're already loading it so, again, we can simply use that. For example,

  \node[frame,right=1cm of FF, xshift=3cm, label={below:$\F^{\prime}$}] (Fp){};

In place of shapes, we want shapes.geometric which provides the ellipse. The updated version of arrows is arrows.meta but you aren't using it, so I've not loaded either here.

\usetikzlibrary{shapes.geometric,positioning,fit}

\documentclass{article}
\usepackage{tikz,amssymb}
\usetikzlibrary{shapes.geometric,positioning,fit}
\newcommand{\R}{\mathcal{R}}
\newcommand{\F}{\mathfrak{F}}
\begin{document}
\tikzset{% \tikzstyle is deprecated
  frame/.style={draw,ellipse,minimum height=6cm,minimum width=2cm},
  world/.style ={draw,circle,fill=black, inner sep=0pt, minimum size=3pt},
}
\begin{tikzpicture}[node distance=3cm, transform canvas={scale=0.9}]
  \node[frame] (F0){};
  \node at ([xshift=-1em, yshift=-4em]F0.north) [world, label={70:$(w,0)$}] (w0){};
  \node at ([yshift=3em]F0.south west) [world, label={-70:$(v,0)$}] (v0){};
  \path[->] (w0) edge[bend left=10] node[right] {$\R^{0}$} (v0);

  \node[frame, right=1cm of F0] (F1){};
  \node at ([xshift=-1em, yshift=-4em]F1.north) [world, label={70:$(w,1)$}] (w1){};
  \node at ([yshift=3em]F1.south west) [world, label={-70:$(v,1)$}] (v1){};
  \path[->] (w1) edge[bend left=10] node[right] {$\R^{1}$} (v1);

  \node (FF) [fit=(F0) (F1), draw=white, label={below:$\F \oplus \F$}] {};

  \node[frame,right=1cm of FF, xshift=3cm, label={below:$\F^{\prime}$}] (Fp){};
  \node at ([yshift=-4em]Fp.north) [world, label={70:$\hat{w}$}] (w){};
  \node at ([yshift=3em]Fp.south west) [world, label={-70:$\hat{v}$}] (v){};
  \node at ([yshift=3em]Fp.north east) [world, label={70:$w^{\prime}$}] (wp){};

  \path[->] (w) edge[bend left=10] node[right] {$\R^{\prime}$}(v);

  \path[-] (wp.west) edge[bend right,draw=gray, dashed] node [below]{} (Fp.north);
  \path[-] (wp.south east) edge[bend left,draw=gray, dashed] node [below]{} (Fp.north east);

  \path[->] (w0) edge[bend left=80, dashed] node[above] {$g$}(w);
  \path[->] (w1) edge[bend left=60,dashed] node[above] {$g$}(wp);
  \path[->] (v0) edge[bend left=8,dashed] node[pos=.6,above] {$g$}(v);
  \path[->] (v1) edge[bend right=100,dashed] node[above] {$g$}(v);
\end{tikzpicture}
\end{document}

fitted nodes

2

The following is the updated code; thanks to AJN to their response! :)

\documentclass{article}
\usepackage{float, latexsym, tikz, amssymb, amsmath, amsthm, graphicx, caption}

\usetikzlibrary{shapes,arrows,positioning,fit,matrix,calc}

\newsavebox\disjUn

\newcommand{\R}{\mathcal{R}}
\newcommand{\F}{\mathfrak{F}}

\begin{document}
    \tikzstyle{frame}=[draw,ellipse,minimum height=6cm,minimum width=2cm]
    \tikzstyle{world} =[draw,circle,fill=black, inner sep=0pt, minimum size=3pt]

    \begin{lrbox}{\disjUn}
    \begin{tikzpicture}[remember picture, node distance=3cm]
        \node[frame] (F0){};
        \node at ([xshift=-1em, yshift=-4em]F0.north) [world, label={70:$(w,0)$}] (w0){}; 
        \node at ([yshift=3em]F0.south west) [world, label={-70:$(v,0)$}] (v0){};
        \path[->] (w0) edge[bend left=10] node[right] {$\R^{0}$} (v0);

        \node[frame, right of=F0] (F1){};
        \node at ([xshift=-1em, yshift=-4em]F1.north) [world, label={70:$(w,1)$}] (w1){}; 
        \node at ([yshift=3em]F1.south west) [world, label={-70:$(v,1)$}] (v1){};
        \path[->] (w1) edge[bend left=10] node[right] {$\R^{1}$} (v1);
    \end{tikzpicture}
    \end{lrbox}

    \begin{figure}[H]
    \centering
    \begin{tikzpicture}[remember picture, node distance=3cm]
        \node[draw=white, label={below:$\F \oplus \F$}] (FF) {\usebox\disjUn};

        \node[frame,right of=FF, xshift=3cm,label={below:$\F^{\prime}$}] (Fp){};
        \node at ([yshift=-4em]Fp.north) [world, label={70:$\hat{w}$}] (w){}; 
        \node at ([yshift=3em]Fp.south west) [world, label={-70:$\hat{v}$}] (v){};
        \node at ([yshift=3em]Fp.north east) [world, label={70:$w^{\prime}$}] (wp){};

        \path[->] (w) edge[bend left=10] node[right] {$\R^{\prime}$}(v);

        \path[-] (wp.west) edge[bend right,draw=gray, dashed] node [below]{} (Fp.north);
        \path[-] (wp.south east) edge[bend left,draw=gray, dashed] node [below]{} (Fp.north east);

        \path[->] (w0) edge[bend left=80, dashed] node[above] {$g$}(w);
        \path[->] (w1) edge[bend left=60,dashed] node[above] {$g$}(wp);
        \path[->] (v0) edge[bend left=8,dashed] node[above] {$g$}(v);
        \path[->] (v1) edge[bend right=100,dashed] node[above] {$g$}(v);
    \end{tikzpicture}
    \end{figure}
\end{document}

Which produces the following output:

enter image description here

Funnily enough, if you remove the 'remember picture' argument from the outer TiKz picture and compile in TexStudio with PdfLaTeX by pressing F6, the picture breaks in different ways with a cycle of length 2 LOL. Not sure how I can explain this... Will definitely require more research! :) Thanks again for everyone's assistance!

6
  • Once again, don't nest TikZ pictures but use a pic/.
    – percusse
    Mar 25, 2016 at 11:26
  • So is this the result you wanted? I can't really tell if this is an answer or should be added into your question ;).
    – cfr
    Mar 25, 2016 at 13:21
  • @cfr Well, I was able to draw the desired edges, so I thought it was good enough at the time :) However, your solution is much more elegant!!! I'm going to study it, and amend my document... Thank you for all your help!
    – Wanda B.
    Mar 25, 2016 at 17:57
  • @percusse I guess I figured that since it compiled, it was fine. LOL. Also, from what I read (with bleary eyes, admittedly, so I probably missed something), it wasn't a critical flaw to nest TiKz pictures, other than how ugly it is! But then cfr came up with a solution that totally didn't require nesting of any sort! Thanks for your advice and help these long hours :D I'm definitely bookmarking your suggested reading though!
    – Wanda B.
    Mar 25, 2016 at 18:02
  • 1
    It was a genuine query. I just wasn't sure if that's what you wanted to draw or if there was something which needed changing. Nesting the pictures is problematic, but that doesn't stop it being an answer - just probably not the best possible one ;).
    – cfr
    Mar 25, 2016 at 21: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.