This question resulted from the question here
I want to produce a curly brace which spans some lines of text.
The problem is that I have to align the x coordinate manually, which is not a clean solution.
Currently I use
\begin{frame}{Example}
\begin{itemize}
\item The long Issue 1
\tikz[remember picture] \node[coordinate,yshift=0.7em] (n1) {}; \\
spanning 2 lines
\item Issue 2
\tikz[remember picture] \node[coordinate, xshift=1.597cm] (n2) {};
\item Issue 3
\end{itemize}
\visible<2->{
\begin{tikzpicture}[overlay,remember picture]
\draw[thick,decorate,decoration={brace,amplitude=5pt}]
(n1) -- (n2) node[midway, right=4pt] {One and two are cool};
\end{tikzpicture}
} % end visible
\end{frame}
which produces the desired result:
The unsatisfying thing is, that I had to figure out the xshift value of 1.597cm by trial and error (more or less)
Without xshift argument the result is:
I guess there is an elegant way to avoid the explicit xshift value.
The best way would it imho be to calculate the maximum x value of two nodes and use this, (as already suggested by Geoff)
But it would already be very handy to be able to explicitly define the absolute xvalues of both nodes while keeping their current y values. This would avoid the fiddly procedure of adapting the third post decimal position to ensure that the brace looks vertical.
This requires \usetikzlibrary{calc}. There may be a cleaner way, though.
Remove the "xshift" from node n2 and then use:
\begin{tikzpicture}[overlay,remember picture]
\path (n2) -| node[coordinate] (n3) {} (n1);
\draw[thick,decorate,decoration={brace,amplitude=5pt}]
(n1) -- (n3);
\node[right=4pt] at ($(n1)!0.5!(n3)$) {One and two are cool};
\end{tikzpicture}
Here's a version using the fit library which doesn't require you to worry about which line is longest, at the expense of marking each line.
\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
\usetikzlibrary{fit}
\newcommand{\bracemark}[1]{\tikz[remember picture] \node[inner sep=0pt] (#1) {\vphantom{X}};}
\begin{document}
\begin{frame}{Example}
\begin{itemize}
\item The long Issue 1 \bracemark{n1} \\
gratuitious long line of text \bracemark{n2} \\
spanning 3 lines \bracemark{n3}
\item Issue 2 \bracemark{n4}
\item Issue 3
\end{itemize}
\visible<2->{
\begin{tikzpicture}[overlay,remember picture]
\node [inner sep=0pt, fit=(n1) (n2) (n3) (n4)] (bracemarks) {};
\draw[thick,decorate,decoration={brace,amplitude=5pt}]
(bracemarks.north east) -- (bracemarks.south east) node[midway, right=4pt] {One and two are cool};
\end{tikzpicture}
} % end visible
\end{frame}
\end{document}
The yshift needed in the OP's sample is avoided by making the nodes actual nodes (as opposed to coordinates) with a zero-width X as text.
Related
I'm currently working on some homework for my Theory of Computation course; right now I am creating state diagrams in LaTeX with the TikZ library (in Overleaf). We have a template file where problems are listed in an itemize block and I am inserting tikzpicture blocks to create the state diagrams in each of the item blocks.
\begin{itemize}
\item[a.] $\{w~|~w$ begins with a $\input{1}$ and ends with a $\input{0} \}$
\begin{figure}[ht]
\begin{tikzpicture}
\node[state, initial] (q0) {$q_0$};
\node[state, right of=q0] (q1) {$q_1$};
\node[state, below of=q1] (qR) {$q_R$};
\node[state, accepting, right of=q1] (q2) {$q_2$};
\draw (q0) edge[bend right, below] node{0} (qR)
(qR) edge[loop below] node{0,1} (qR)
(q0) edge[above] node{1} (q1)
(q1) edge[loop above] node{1} (q1)
(q1) edge[bend left, above] node{0} (q2)
(q2) edge[bend left, below] node{1} (q1)
(q2) edge[loop right] node{0} (q2);
\end{tikzpicture}
\end{figure}
... Cut some code out here to save space
\item[d.] The empty set
\begin{figure}[ht]
\begin{tikzpicture}
\node[state, initial] (q) {$q$};
\draw (q) edge[loop right, above] node{0,1} (q);
\end{tikzpicture}
\end{figure}
\end{itemize}
The thing that is bothering me, and I know it's not a huge deal and I'm just being anal, is that it comes out looking like this when compiled:
Is there a way I could change this code so that both the problem statement and my solution diagram will fit on the same page of the pdf? It really bothers me to look at it and I run into stuff like this a lot working with LaTeX. Thanks!
A \vbox might do what you want:
\item \vbox{
% the contents you want to enclose on the same page
}
I currently have the code below which produces the later output. I would like to generate the 10 points randomly as I already am. But instead of having blue dashed lines connecting to the the location (0,0), I want them to connect to the other dots if the distance is less than 4cm away.
I attempted things such as storing the data into arrays but updating and accessing the values was not working. I attempted nested for loops but handling the seed became difficult. What is a good way to do this?
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw[step=0.5cm,color=gray] (-2.5,-2.5) grid (2.5,2.5);
\pgfmathsetseed{2}
\foreach \x in {1,...,10}
{
\pgfmathrandominteger{\a}{-240}{240}
\pgfmathrandominteger{\b}{-240}{240}
\fill [color=red,anchor=center](\a*0.01,\b*0.01) circle (0.1);
% CHANGE HERE
\draw [color=blue,densely dotted] (\a*0.01,\b*0.01) -- (0.0,0.0);
};
\end{tikzpicture}
\end{document}
I seemed to have figured out a solution (not ideal but works for this case).
The key was to use the \pgfmathparse for performing the if statement to get a 0 or 1 to use in \ifnum.
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
\draw[step=0.5cm,color=gray] (-2.5,-2.5) grid (2.5,2.5);
\pgfmathsetseed{2}
\foreach \x in {1,...,10}
{
\pgfmathrandominteger{\a}{-240}{240}
\pgfmathrandominteger{\b}{-240}{240}
\fill [color=red,anchor=center](\a*0.01,\b*0.01) circle (0.1);
\pgfmathsetseed{2}
\foreach \y in {0,...,\x}
{
\pgfmathrandominteger{\c}{-240}{240}
\pgfmathrandominteger{\d}{-240}{240}
\tikzmath{\i=(\a*0.01-\c*0.01)^2;}
\tikzmath{\j=(\b*0.01-\d*0.01)^2;}
\tikzmath{\k=\i+\j;}
\pgfmathparse{\k < 4.0 ? 1 : 0}
\ifnum\pgfmathresult=1
\draw [color=blue,densely dotted] (\a*0.01,\b*0.01) -- (\c*0.01,\d*0.01);
\fi
};
};
\end{tikzpicture}
\end{document}
Say I want to construct a circulant graph in TikZ, with a variable number of nodes, labelled v0, v1, ..., v_n-1 for some n of my choice (say, 5).
I'd like to be able to use the \foreach command in TikZ to iteratively (1) define the nodes, and (2) connect the nodes. I'd like to be able to connect v_i to v_(i+1) and v_i to v_{i+2}, say.
\foreach \i in {0, ..., 4}
{\path (\i*72:3) node (v\i) {};}
constructs the nodes perfectly. But then when I want to draw some lines,
\foreach \i \in {0, ..., 3}
{ \draw (v\i) -- (v{\i+1}); } ????
doesn't work. Nor does
\foreach \i / \j in {0/1, ..., 3/4}
{ \draw (v\i) -- (v{\j}); }
I get an error "no such shape v0" or something like that.
I know this must be totally easy to do, but I can't figure out how. Any suggestions?
As a followup, it would be nice to be able to connect v_i and v_{i+4} or something, with a single \foreach command, and have TikZ/pgf do the modular arithmetic for me without having to worry about spilling over.
This worked for me:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes,fit,arrows,positioning}
\tikzstyle{vertex} = [circle, draw, thick, text centered]
\tikzstyle{edge} = [draw, thick,->]
\begin{document}
\begin{tikzpicture}[scale=1]
\foreach \x in {0,...,6}
\node[vertex] (\x) at (\x*360/7:3) {v\x};
\foreach \x/\y in {0/1,1/2,2/3,3/4,4/5,5/6,6/0}
\draw[edge] (\x) to (\y);
\end{tikzpicture}
\end{document}
The syntax {0/1,...,5/6} did not work for me. But I admit, I spent a bit of time trying to find a good solution, and I'm still not totally satisfied.
Another solution, achieved editing the code by Steve Tjoa:
\documentclass[tikz,border=1mm]{standalone}
\usetikzlibrary{arrows}
\begin{document}
\begin{tikzpicture}[thick]
\foreach \x in {0,...,4}{%
\node [circle, draw] at (\x*72:3) {$v_{\x}$};
\draw [->] (\x*72+10:3) arc (\x*72+10:\x*72+62:3);
}
\end{tikzpicture}
\end{document}
This is what I'm trying to do
\begin{tikzpicture}
[node distance = 1cm, auto,font=\footnotesize,
% STYLES
every node/.style={node distance=1.3cm},
comment/.style={rectangle, inner sep= 5pt, text width=4cm, node distance=0.25cm, font=},
module/.style={rectangle, drop shadow, draw, fill=black!10, inner sep=5pt, text width=3cm, text badly centered, minimum height=0.8cm, font=\bfseries\footnotesize\sffamily,rounded corners},
selected/.style={fill=red!40}]
\node [module] (nodeA) {node A};
\node [module, below of=nodeA] (nodeA) {node B};
\only<1>{
\node [comment, text width=6cm, right=0.25 of nodeA] {short description of Node A};
\node [comment, text width=6cm, right=0.25 of nodeB] {short description of Node B};
}
\only<2>{
\node [selected] (nodeA) {};
\node [comment, text width=6cm, right=0.25 of nodeA] {long description of node A};
}
\only<3>{
\node [selected] (nodeB) {};
\node [comment, text width=6cm, right=0.25 of nodeA] {long description of node B};
}
\end{tikzpicture}
The problem is
\node [selected] (nodeB) {};
creates a new node, but I want it to apply the style for the existing node. Is there any way to do so?
Of course I could have copies of every node in selected state and not-selected state, but I really want to have a normal solution.
I don't think you can do this the way you want to (assuming I understand the question correctly), because once a node is drawn, there's no way to change its appearance. I'd suggest using Beamer's \alt macro:
\alt<2>{\node[module,selected] at (nodeA) {node A};}{\node[module] at (nodeA) {node A};}
\alt<3>{\node[module,selected] at (nodeB) {node B};}{\node[module] at (nodeB) {node B};}
\node[comment,text width=6cm,right=0.25 of nodeA]{\alt<2>{short description}{long description}};
\node[comment,text width=6cm,right=0.25 of nodeB]{\alt<3>{short description}{long description}};
Or something like that (you might have to tinker with the semicolons to get it to work, I can't test that at the moment).
Another option would be to actually just draw a new node. If you include
\node[module,selected] at (nodeA) {node A};
inside \only<2>, that will draw a node that looks just like node A, except with a red background, at the same position at node A. The new node will cover up the original node A.
Sometimes, to avoid repetitions, it may be nice to do something like this:
% #1 Overlay specs.
% #2 Style name.
% #4 Style properties.
\def\onlystyle<#1>#2#3{%
\alt<#1>{%
\tikzset{#2/.style = {#3}}
}{%
\tikzset{#2/.style = {}}
}%
}
Then, if you put, for example, this within a frame:
\onlystyle<2>{selected}{fill = red}
the style selected will be defined as fill = red on the second slide of the animation, and as a style with no effect whatsoever on every other slide. Then, you can write a readable figure such as:
\begin{tikzpicture}
\node at (0, 0) {A};
\node[selected] at (1, 0) {B};
\node at (2, 0) {C};
\end{tikzpicture}
and the “B” node will be highlighted on the second slide. This way, you don't have to copy-paste tons of node definitions.
Of course, it cannot be applied to every single animation need, but I like to keep this technique up my sleeve.
I found yet another solution, which has advantages (more functionality!) compared to all previous solutions, including the one I posted before.
First I mention the improved solution, then I explain why it actually shows more functionality than all other solutions.
The following solution, adapted from How can I make Beamer overlays with TikZ node attributes?, uses an additional tikz library and uses a parameter for the slide number-dependent attribute (for the slide numbers, of course). Note that the tikz setting has to be done outside the frame now.
\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{overlay-beamer-styles}
\begin{document}
\begin{frame}{With code/node duplication (explicit frame numbers)}
\begin{tikzpicture}
[every node/.style={draw,circle},
redStyle/.style={fill=red},
blueStyle/.style={fill=blue}]
\node<1> [] (A) {A}; % no style
\node<2> [redStyle] (A) {A}; % red style
\node<3> [blueStyle] (A) {A}; % blue style
\node [right of=A] (B) {B};
\draw [-latex] (A) -- (B) ;
\end{tikzpicture}
\end{frame}
\tikzset{
every node/.style={draw,circle},
redStyle/.style={fill=red}, redStyle on/.style={alt=#1{redStyle}{}},
blueStyle/.style={fill=blue}, blueStyle on/.style={alt=#1{blueStyle}{}}}
\begin{frame}{\textbf{Without} code/node duplication (explicit frame numbers)}
\begin{tikzpicture}
\node [redStyle on=<2>,blueStyle on=<3>] (A) {A};
\node [right of=A] (B) {B};
\draw [-latex] (A) -- (B) ;
\end{tikzpicture}
\end{frame}
\tikzset{
every node/.style={draw,circle},
redStyle/.style={fill=red}, redStyle on/.style={alt=#1{redStyle}{}},
blueStyle/.style={fill=blue}, blueStyle on/.style={alt=#1{blueStyle}{}}}
\begin{frame}{\textbf{Without} code/node duplication (relative frame numbers)}
\begin{tikzpicture}
\node [redStyle on=<+(1)>,blueStyle on=<+(1)>] (A) {A};
\node [right of=A] (B) {B};
\draw [-latex] (A) -- (B) ;
\end{tikzpicture}
\end{frame}
\end{document}
Now the explanation why this solution is the best mentioned so far, i.e. which additional features it has and why (or when) they are relevant. Well, simply because the respective property does not have to show at the same slide number for different usages within the same frame. Simple example:
Let's say you have a simple tree, i.e. nodes with directed edges connecting them. Say you want to make some of the edges bold in specific slides. Of course you have multiple edges, so clearly they do not all become bold at the very same time! Some edges get bold at frame numbers m to n, others get bold at x and y. This can now be trivially realized with using the node (or edge, in this case) properties timedBold on=<m-n> and timedBold on=<x,y>.
Note that there is yet another possibility, which to me seems a bit better than the previous two suggestions, because it has less code duplication (compared to David Z's solution), and because (compared to Alice M.'s solution) you do not need to define a new command that you had to define outside the frame (though defining this additional command is probably not an issue to anybody). In principle, the following suggestion seems to be closely related to the suggestion by Alice M.
Anyway, the solution is a direct application of How to modify a node in TikZ when using beamer's overlays.
Is basically just re-defines a style based on the frame number. See the following minimal example, second or third frame. (I re-did the minimal example since I regard the given one extremely complicated; it was certainly not a minimal example, and also not working on its own.)
\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\begin{frame}{With code/node duplication (explicit frame numbers)}
\begin{tikzpicture}
[every node/.style={draw,circle},
redStyle/.style={fill=red},
blueStyle/.style={fill=blue}]
\node<1> [] (A) {A}; % no style
\node<2> [redStyle] (A) {A}; % red style
\node<3> [blueStyle] (A) {A}; % blue style
\node [right of=A] (B) {B};
\draw [-latex] (A) -- (B) ;
\end{tikzpicture}
\end{frame}
\begin{frame}{\textbf{Without} code/node duplication (explicit frame numbers)}
\only<1>{\tikzset{colorStyle/.style={}}} % no style
\only<2>{\tikzset{colorStyle/.style={fill=red}}} % red style
\only<3>{\tikzset{colorStyle/.style={fill=blue}}} % blue style
\begin{tikzpicture}
[every node/.style={draw,circle}]
\node [colorStyle] (A) {A}; % frame-dependent style
\node [right of=A] (B) {B};
\draw [-latex] (A) -- (B) ;
\end{tikzpicture}
\end{frame}
\begin{frame}{\textbf{Without} code/node duplication (relative frame numbers)}
\only<+>{\tikzset{colorStyle/.style={}}} % no style
\only<+>{\tikzset{colorStyle/.style={fill=red}}} % red style
\only<+>{\tikzset{colorStyle/.style={fill=blue}}} % blue style
\begin{tikzpicture}
[every node/.style={draw,circle}]
\node [colorStyle] (A) {A}; % frame-dependent style
\node [right of=A] (B) {B};
\draw [-latex] (A) -- (B) ;
\end{tikzpicture}
\end{frame}
\end{document}
I am producing some latex beamer slides (but I think it is not a beamer specific question per se).
I have the following:
\begin{itemize}
\item Issue1
\item Issue2
\item Issue3
\end{itemize}
Now, I want to have a right curly brace (i.e. '}') behind the items spreading over issue1 and issue2. And of course I want to write something behind that curly brace.
In a perfect world I would write something like:
\begin{itemize}
\left .
\item Issue1
\item Issue2
\right \} One and Two are cool
\item Issue3
\end{itemize}
This does not work because I am not in a math environment and I can not put the whole snippet inside a math environment because itemize would not work in that case.
Is there a clean solution or a hack to produce my desired result?
Regards,
Bastian.
I'd use tikz and make an overlay.
First include the proper packages (you may not need to include tikz since this is a beamer question):
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
Then when you make your list, give names to the places after each item:
\begin{itemize}
\item Issue 1
\tikz[remember picture] \node[coordinate,yshift=0.5em] (n1) {};
\item Issue 2
\tikz[remember picture] \node[coordinate] (n2) {};
\item Issue 3
\end{itemize}
(Note: I shifted the y value up by 1/2 of a line maybe more would be better.)
Because we used remember picture we can refer to these places in an overlay:
\begin{tikzpicture}[overlay,remember picture]
\path (n2) -| node[coordinate] (n3) {} (n1);
\draw[thick,decorate,decoration={brace,amplitude=3pt}]
(n1) -- (n3) node[midway, right=4pt] {One and two are cool};
\end{tikzpicture}
The path is there to deal with items that do not have the same width. This edit comes from ESultanik's answer.
The result is:
Side note: You can remove all of the remember picture options and add the following to automatically add remember to all pictures:
\tikzstyle{every picture}+=[remember picture]
You could (ab)use a table instead:
\documentclass{article}
\usepackage{multirow}
\begin{document}
\begin{tabular}{ll}
\textbullet Issue 1 & \multirow{2}{*}{{\LARGE \}} One and Two are cool} \\
\textbullet Issue 2 \\
\textbullet Issue 3 \\
\end{tabular}
\end{document}
produces:
removed dead Imageshack link
Here is Geoffs code with some small adaptions (just for other beamer users)
\begin{frame}{Example}
\begin{itemize}
\item The long Issue 1
\tikz[remember picture] \node[coordinate,yshift=0.7em] (n1) {}; \\
spanning 2 lines
\item Issue 2
\tikz[remember picture] \node[coordinate, xshift=1.597cm] (n2) {};
\item Issue 3
\end{itemize}
\visible<2->{
\begin{tikzpicture}[overlay,remember picture]
\draw[thick,decorate,decoration={brace,amplitude=5pt}]
(n1) -- (n2) node[midway, right=4pt] {One and two are cool};
\end{tikzpicture}
} % end visible
\end{frame}
Ressult (2nd slide of that frame):
The adaptions are:
added the visible command (because I think it is useful to blend in the brace later)
made the items more complex so the use of xshift became necessary (I figured out the xshift value simply by try and error so thats a drop of bitterness) Edit 2018-12-23: manual try-and-error shifting can be overcome by using this method: (n1 -| n2) -- (n2) instead of (n1) -- (n2).
One way to get around this would be to use a math environment like align, put the bullet points by hand (with \bullet ), and then use the resources of the math environment for big braces and such.
I did something similar once. I let the list be in a column to the left, and in the right column, I did the $\right\}$-thing so that it was as tall as some \mbox or something (which I decided with \vphantom or something similar). Unfortunately I don't have time to dig it out... I actually don't have time to be at SO at all right now ;)
I tried my idea, below. It doesn't work: unfortunately, the vboxes produced by the itemize environment all have width \textwidth.
The UI of my suggestion is nice, and by redefining \item it should be possible to get the item vboxes be of reasonable width. Or calculate a reasonable width for the vboxes containing the items. But since there are functional solutions already, I won't spend anymore time on this.
\documentclass{article}
\def\setgrouptext#1{\gdef\grouptext{#1}}
\newenvironment{groupeditems}{\begin{displaymath}\left.\vbox\bgroup\setgrouptext}{%
\egroup\right\rbrace\hbox{\grouptext}\end{displaymath}}
\begin{document}
\begin{itemize}
\item Line 1
\begin{groupeditems}{Lines 2 and 3 together!}
\item Line 2
\item Line 3
\end{groupeditems}
\item Line 4
\end{itemize}
\end{document}