18

I would like to reproduce this kind of figure:

enter image description here

I'm wondering what's the best way to achieve that with TikZ.

My guess is to draw an element composed of a circle + a link and to link this element by specifying only an angle (since the distance is always the same).

Any suggestions?

1

5 Answers 5

26

A very simple proof of concept example:

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw[fill] (0,0) circle (.5) -- ++(10:2) circle (.5) -- ++(-20:2) circle (.5);
\end{tikzpicture}
\end{document}

enter image description here

Of course one could do some very nice tweaks such as building an own style for the lines and circles, but the code above contains at least everything that is needed to reach your goal.

Depending on what you need exactly, it was also very easily possible to automate the generation of such a chain including for example random angles between the beads.

Here's a version using a \foreach to specify a list of angles:

\documentclass{article}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\tikzset{bead/.style={circle,fill=black,inner sep=3pt}}

\draw node[bead] {} (0,0)
\foreach \angle in {10,40,50,-50,0,150,30,-60,45,45,0}
  { -- ++(\angle:1) node[bead] {}};
\end{tikzpicture}

\end{document}

enter image description here

And a version with relative angles (Qrrbrbirlbel suggested this version in chat and I like it more than the one I initially had):

\documentclass{article}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\tikzset{bead/.style={circle,fill=black,inner sep=3pt}}
\def\angle{0}

\draw node[bead] {} (0,0)
\foreach \stepangle[evaluate=\stepangle as \angle using \angle+\stepangle, remember=\angle] in {10,20,-30,-60,135,-20,-30,0}
  { -- ++(\angle:1) node[bead]{}};
\end{tikzpicture}

\end{document}

enter image description here

8
  • 3
    If you don't mind non-tikz solutions, I can provide an Asymptote example which lets to construct bead chains in a form like pos>0>45>-45>90>135.
    – g.kov
    Mar 31, 2013 at 16:11
  • 3
    @g.kov I'd encourage answers using different tools.
    – egreg
    Mar 31, 2013 at 22:27
  • 2
    @g.kov: It would be nice to have examples of different methods. I request you to make such answers like a tutorial type with more details so that we (atleast I) will start learning. Asymptote is superior in certain aspects.
    – user11232
    Apr 1, 2013 at 0:15
  • I added a version with a \foreach. Please feel free to roll-back my edit if you don't like it. Apr 1, 2013 at 1:32
  • @Harish Kumar: An asy version added. I tried to make it kind of a tutorial style. If something in the example needs a clarification, please let me know.
    – g.kov
    Apr 1, 2013 at 7:07
16

enter image description here

To fit the original request that a chain is built by specifying only angles, Asymptote provides an operator overloading. An overloaded operator > pair operator>(pair pos=(0,0), real phi) takes a position on the left and an angle on the right, calculates a proper transform (combined rotation and shift) and calls a procedure bead that actually draws the bead with radial shading and a link. Thus the chains are constructed either as pos=pos>0>45>-45>90>135 which updates the position, or just pos>0>45>-45>90>135; pos>90>90>90; to draw several branches from the same origin. Note that a numeric comparison with > still works, since it corresponds to a different signature of parameters. beads.asy:

size(300,300);
real linkLen=1, linkWidth=2pt; 
real rl=2+linkLen;              // distance between beads
guide g=(1,0)--(1+linkLen,0);   // a link
pen beadColor=orange;
pen linkColor=beadColor;
void bead(transform t){  
  draw(t*g,linkColor+linkWidth);
  radialshade(t*unitcircle,
    beadColor,shift(t)*(-0.4,0.3),0.01
   ,black,shift(t)*(-0.4,0.3),1.5); 
}
pair operator>(pair pos=(0,0), real phi){
  transform t=shift(pos.x,pos.y)*rotate(phi);
  bead(t); // draw a bead with a link
  pos+=rl*(Cos(phi),Sin(phi)); // Sin, Cos - in degrees, sin, cos - in radians
  return pos;
}; 

pair pos=(0,0); // start point

if(exp(1)>pi){ // note that ">" still works the usual way to compare numbers
  // this branch is skipped 
}else{
  pos=pos>0>45>-45>90>135; // draw a bead chain and update the position
  pos>0>45>-45>90>135;     // continue the chain without updating the start position
  beadColor=lightyellow;
  linkColor=lightblue;
  pos>90>90>90;           // draw another branch from saved position, with different colours
}

A standalone pdf is produced by asy -f pdf beads.asy

Edit: This is an inline version, beads-inline.tex:

\documentclass[10pt,a4paper]{article}
\usepackage{lmodern}
\usepackage{soul}
\usepackage{caption}
\usepackage[inline]{asymptote}
\def\asydir{}
\begin{asydef}
// Global Asymptote definitions 
real linkLen=1, linkWidth=2pt; 
real rl=2+linkLen;              // distance between beads
guide link=(1,0)--(1+linkLen,0);   // a link
pen beadColor=orange;
pen linkColor=beadColor;
void bead(transform t){  
  draw(t*link,linkColor+linkWidth);
  radialshade(t*unitcircle,
    beadColor,shift(t)*(-0.4,0.3),0.01
   ,black,shift(t)*(-0.4,0.3),1.5); 
}
pair operator>(pair pos=(0,0), real phi){
  transform t=shift(pos)*rotate(phi);
  bead(t); // draw a bead with a link
  pos+=rl*(Cos(phi),Sin(phi)); // Sin, Cos - in degrees, sin, cos - in radians
  return pos;
}; 
pair pos;
\end{asydef}

\begin{document}

\newcommand\hi[1]{\bf Hello \st{Word} #1!}

\center
\captionof{figure}{Example of bead chain building.}
\begin{asy}
  size(150,150);
  pos>0>60>0>70;   
  beadColor=lightyellow;
  pos>0>-60>0>-70;
  pos=  pos>0>0>0>0;     
  label("\textbf{Example}",pos,SE);
\end{asy}

\center
\captionof{figure}{Another example of bead chain building.}
\begin{asy}
  size(150,150);
  beadColor=lightyellow;
  linkColor=lightblue;
  pos=pos>90>42>0>0>0>0>0>0>-130;   
  label(
     "\parbox{8cm}{"
     "The following command \texttt{\textbackslash hi} is defined \\"
     +"in the main \LaTeX\ document:\\"
     "\hi{\LaTeX}}"
     ,pos);
\end{asy}

\end{document}

To process it with latexmk, create file latexmkrc:

sub asy {return system("asy '$_[0]'");}
add_cus_dep("asy","eps",0,"asy");
add_cus_dep("asy","pdf",0,"asy");
add_cus_dep("asy","tex",0,"asy");

and run latexmk -pdf beads-inline.tex. The result looks like

enter image description here

For more details consult the manual at: asymptote development page at sourceforge or, in case if you happened to be a lucky TeX Live user, just type texdoc asymptote.

4
  • Thank you for Asymptote side of graphics typesetting. Apr 1, 2013 at 6:58
  • 2
    @texenthusiast: Perhaps, the Asymptote just needs more ready-to-use templates to become more popular.
    – g.kov
    Apr 1, 2013 at 7:25
  • Nice. Is it possible to compile this from within the .tex file?! Also, (I was wondering looking at your previous answers) how do you find out the coordinates? Is there any short cut?. It will be nice if you add the links to reference/learning material. +1 indeed.
    – user11232
    Apr 1, 2013 at 15:46
  • @Harish Kumar: The main documentation is at http://asymptote.sourceforge.net/asymptote.pdf. If you mean the bead coordinates, in the example they are stored in pos variable and update happens in a line pos+=rl*(Cos(phi),Sin(phi));.
    – g.kov
    Apr 1, 2013 at 19:00
13

With PSTricks.

enter image description here

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-plot}

\def\X(#1){#1}
\def\Y(#1){3+2*sin(#1)}

\psset{algebraic,showpoints,dotscale=3}

\begin{document}

\begin{pspicture}(-1,-1)(7,6)
    \psparametricplot[plotpoints=10]{-0.5}{6.5}{\X(t)|\Y(t)}
\end{pspicture}
\end{document}

\end{document}

Animation

enter image description here

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-plot}

\def\X(#1){#1}
\def\Y(#1){3+2*sin(#1)}

\psset{algebraic,showpoints,dotscale=3}

\begin{document}

\multido{\i=2+1}{21}{%
\begin{pspicture}(-1,-1)(7,6)
    \psparametricplot[plotpoints=\i]{-0.5}{6.5}{\X(t)|\Y(t)}
\end{pspicture}}
\end{document}

\end{document}

The latest edit

If you need equally-spaced beads, see the following:

enter image description here

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pstricks-add}

\begin{document}

\begin{pspicture}[showgrid](-1,-1)(8,3)
    \psStartPoint(0,0)
    \psforeach{\i}{10,40,50,-50,0,150,30,-60,45,45,0}{\psVector[arrows=-*](1;\i)}
\end{pspicture}

\end{document}

or

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-node}

\begin{document}

\begin{pspicture}[showgrid](-1,-1)(8,3)
    \pnode(0,0){A}
    \psforeach{\i}{10,40,50,-50,0,150,30,-60,45,45,0}{
    \pnode[!1 \i\space PtoC](A){B}
    \pscircle*(B){4pt}
    \psline(A)(B)
    \pnode(B){A}
    }
\end{pspicture}

\end{document}
4
  • What is the PSTricks equivalent to the \foreach solution by Benedikt Bauer/Gonzalo Medina, i.e. fixed width and specified angles? Apr 1, 2013 at 1:37
  • @Qrrbrbirlbel: well done! Apr 1, 2013 at 2:23
  • There is no more technique with \pspolylineticks which is very sophisticated but its documentation is really confusing to grasp. Apr 2, 2013 at 1:02
  • The second code does not work me. It gives the following error: Undefined control sequence. ...lot[plotpoints=10]{-0.5}{6.5}{\X(t)|\Y(t)}. How to solve it?
    – bmv
    Nov 17, 2017 at 11:03
5

Another TikZ solution that uses ducks turtles! :)

The turtle library is well-explained in its own chapter in the PGF manual, chapter 54/59 “Turtle Graphics Library”:

This little library defines some keys to create simple turtle graphics in the tradition of the Logo programming language. These commands are mostly for fun, but they can also be used for more “serious” business.

Keys

  • bead node style: a node style for the beads (→ Benedikt Bauer’s answer);
  • bead style: an insert path that makes it easy to include a bead node, it accepts one optional parameter to customize the bead node;
  • bead path style: this is a to path that includes a bead node at the start coordinate and your usual line to -- to the target coordinate;
  • turtle/beads style: this install all necessary styles inside the turtle key:
    • the how style is set to the bead path style, and
    • the starting direction is set by turning the turtle to the right

Now we would be able to say

\draw (0,0) [turtle={beads, right=10, forward, left=20, forward, …}];

and so on and it would work quite well, but the lazy turtle just wants to know the (relative) directions it has to head.

This is why I defined an additional turn and step style in the turtle path.
When used with the .list handler we can process a comma-delimited list of (relative) angles very easily:

\draw (0,0) [turtle={beads,turn and step/.list={10,20,-30,-60,135,-20,-30,0}}] [bead];

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{turtle}
\tikzset{
    bead node/.style={circle,fill=black,inner sep=3pt},
    bead path/.style={to path={ [bead] -- (\tikztotarget)}},
    bead/.style={insert path={node[bead node]{}}},
    turtle/beads/.style={how/.style={bead path},right},
    turtle/turn and step/.style={left=#1,forward}
}
\begin{document}
\begin{tikzpicture}[turtle/distance=1cm]
\draw (0,0) [turtle={beads,turn and step/.list={10,20,-30,-60,135,-20,-30,0}}] [bead];
\end{tikzpicture}
\end{document}

Output

enter image description here

4

Interesting question for me because tkz-graph is a possibility o draw this kind of graph but I created the possibility to add vertices with polar coordinates, I need to use the origin and not the last vertex. So I need to find a trick to build the graph.

\documentclass[margin=.25cm]{standalone}
\usepackage{tkz-graph}

\begin{document}
\begin{tikzpicture}
\GraphInit[vstyle=Art]% Init the graph and choice a style
\SetVertexNoLabel% no label
\Vertex{A} 
\foreach \a in {45,10,30,-20,0,-60,-40,-45,-10,-90,+20,0,60,-40}{%
\begin{scope}[shift=(A)]% polar from the last vertex
    \Vertex[a=\a , d=1 cm]{B}
    \Edge[style={thick,double=black,double distance=1pt}](A)(B) 
    \pgfnoderename{A}{B}% rename the node, useful macro here
\end{scope}
}
\end{tikzpicture} 

\end{document}

enter image description here

Possible to get a shorter code:

\newcommand{\newVertex}[1]{%
\begin{scope}[shift=(A)]
    \Vertex[a=#1 , d=1 cm]{B} 
\end{scope}    
}

and

\foreach \a in {45,10,30,-20,0,-60,-40,-45,-10,-90,+20,0,60,-40}{%
    \newVertex{\a}
    \Edge[style={thick,double=black,double distance=1pt}](A)(B) 
    \pgfnoderename{A}{B}
}

You must log in to answer this question.

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