8

I would like to draw a five-pointed star with different labels at each point of the star. I reached the example below, which closely follows this question, but I could not replace the numbers with different text labels and I could not remove the line of circle. (I guess that I do not need the foreach either.)

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{shapes}

\begin{document}

\begin{tikzpicture}[n/.style={circle,inner sep=1pt}]
  \draw node [star, star point height=.5cm, minimum size=2cm, inner sep=0,outer sep=0] (s) {}
     circle (1) (s.outer point 1) node[n,label={90:1}]{}
     foreach\x in {4,2,5,3}{--(s.outer point \x) node[n,label={(-45+90*\x):\x}]{}}--cycle;
\end{tikzpicture}

\end{document}

Image

8 Answers 8

8

Revision: a shorter TikZ code

enter image description here

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}[dot/.style={circle,fill,inner sep=2pt}]
\def\r{2}  % radius of the star
\def\n{4}  % n+1 = number of vertexes
\def\Vlabel{{"$V_a$","$V_b$","$V_c$","$V_d$","$V_e$"}}
\foreach \i in {0,...,\n}
\path ({90+\i*360/(\n+1)}:\r) coordinate (V\i) node[dot]{}
+({90+\i*360/(\n+1)}:.4) node{\pgfmathparse{\Vlabel[\i]}\pgfmathresult}
;
\draw (V2)--(V0)--(V3)--(V1)--(V4)--cycle;
\end{tikzpicture}
\end{document}

Is that what you want? You may choose labels using array Vlabel.

enter image description here

// Run on http://asymptote.ualberta.ca/
import math;
unitsize(1cm);
real r=2;
int n=5;
pair[] V;
for(int i=0; i<n; ++i) V.push(r*dir(90+360*i/n));
draw(V[0]--V[2]--V[4]--V[1]--V[3]--cycle);

string[] Vlabel={"$V_a$","$V_b$","$V_C$","$V_d$","$V_e$"};
for(int i=0; i<n; ++i) 
dot(Vlabel[i],align=2dir(degrees(V[i])),V[i],blue);

Update 1. You can embed in LaTex document by loading \usepackage[inline]{asymptote}. For MikTeX, you have to install Asymptote software (this software is already included for TeXlive).

\documentclass{article}
\usepackage[inline]{asymptote}
\begin{document}
\begin{asy}
import math;
unitsize(1cm);
real r=2;
int n=5;
pair[] V;
for(int i=0; i<n; ++i) V.push(r*dir(90+360*i/n));
draw(V[0]--V[2]--V[4]--V[1]--V[3]--cycle);
string[] Vlabel={"$V_a$","$V_b$","$V_C$","$V_d$","$V_e$"};
for(int i=0; i<n; ++i) 
dot(Vlabel[i],align=2dir(degrees(V[i])),V[i],blue);     
\end{asy}
\end{document}

2. In the same way, you can draw with TikZ. I choose Asymptote because array operations in TikZ is not so handy. Do you see how many tricks we have to use? ^^

enter image description here

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\def\r{2}
\def\n{5}
\pgfmathsetmacro\m{\n-1}
\foreach \i in {0,...,\n}
\path ({90+\i*360/\n}:\r) coordinate (V\i);
\draw (V2)--(V0)--(V3)--(V1)--(V4)--cycle;
\def\Vlabel{{"$V_a$","$V_b$","$V_c$","$V_d$","$V_e$"}}
\foreach \i in {0,...,\m}{
\fill[red] (V\i) circle(2pt);
\path (0,0)--(V\i)--([turn]0:.4) 
node{\pgfmathparse{\Vlabel[\i]}\pgfmathresult}; 
}
\end{tikzpicture}
\end{document}
4
  • Nice solution. I see that I can run it with asymptote. I am looking for a solution that I can embed in my tex file as a tikzpicture
    – Andre
    Apr 11 at 19:53
  • @Andre Sure, you can embed in your tex file as a tikz picture or asy picture. See my update!
    – Black Mild
    Apr 11 at 21:14
  • This is great. I will use your solution 2. Can you explain how \pgfmathparse and \pgfmathresult work?
    – Andre
    Apr 12 at 10:26
  • 1
    @Andre the LaTeX's \def command is just word replacing (LaTeX is a word processing, right ^^), so TikZ/PGF does not understand what is \Vlabel[1], for example. To understand it, PGF need to do a parse with \pgfmathparse, and store the result in \pgfmathresult; and then PGF know that \Vlabel[1] is $V_b$.
    – Black Mild
    Apr 12 at 12:39
11

Here is a TikZ solution. You can make the \foreach loop go through the set of labels and use count= to make a numeric value. The evaluate command calculates the angle (\k), which is used to place the nodes and also position the labels.

enter image description here

\documentclass{article}

\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\foreach \l[count=\t, evaluate=\t as \k using \t*72+18] in {label1,label2,label3,label4,label5} 
    {\node[inner sep=0pt,label={\k:\l}] at (\k:2)(n\t){};}
\draw (n1.center)--(n3.center)--(n5.center)--(n2.center)--(n4.center)--cycle;
\end{tikzpicture}

\end{document}

Here is a version built into a macro \labelstar[<radius>]{<label list>} that will work with a list of any (reasonable) length.

enter image description here

\documentclass{article}

\usepackage{tikz}

\newcommand{\labelstar}[2][1]{\begin{tikzpicture}
\foreach \l[count=\n] in {#2}{\xdef\nn{\n}}
\foreach \l[count=\n, evaluate=\n as \t using (\n-1)/\nn*360+90] in {#2} {
    \node[inner sep=0pt] at (\t:#1)(n\n){};
    \node at (\t:(#1+.25){\l};}
\foreach \k[evaluate=\k as \m using {int(1+mod(int(\k+(\nn+1)/2-1)-1,\nn))}] in {1,...,\nn}{
\draw[line cap=round] (n\k.center)--(n\m.center);}
\end{tikzpicture}}

\begin{document}

\labelstar{a,b,c}\qquad
\labelstar{a,b,c,d}\qquad
\labelstar{a,b,c,d,e}\qquad
\labelstar{a,b,c,d,e,f}\qquad

\bigskip
\labelstar{a,b,c,d,e,f,g}\qquad
\labelstar{a,b,c,d,e,f,g,h}\qquad
\labelstar{a,b,c,d,e,f,g,h,i}\qquad
\labelstar{a,b,c,d,e,f,g,h,i,j}\qquad

\bigskip
\labelstar[2]{a,...,q}\qquad
\labelstar[2]{a,...,z}\qquad

\end{document}
7
  • +1: Where in the code do you decode integers into letters? Apr 12 at 5:20
  • 1
    @Dr.ManuelKuehner: I'm not sure I understand the question. \foreach \l[count=\n] in {#2} will assign numbers to \n corresponding to the place of \l in the list. If you're asking about the {a,...,q} construction, that's just a feature of \foreach. It doesn't only work with number sequences.
    – Sandy G
    Apr 12 at 5:27
  • 1
    @Dr.ManuelKuehner: You can print, for example, A with \char 65. Apr 13 at 7:30
  • 1
    I discovered another expression: int(mod(\i+floor(#1/2-1/2),#1)) Apr 13 at 19:07
  • 1
    @TheCodeMocker Thanks for the follow-up. Apr 13 at 19:31
5

A try with MetaPost, included in a LuaLaTeX program. Can be used with any number n of summits (greater than 2, and lower than 27 because of the alphabetic labelling :-))

\documentclass[12pt, border=1mm]{standalone}
\usepackage{luamplib}
    \mplibsetformat{metafun}
    \mplibtextextlabel{enable}
\begin{document}
\begin{mplibcode}
    beginfig(1);
        u = 3cm; n = 5;
        for i = 0 upto n-1:
            z[i] = u*dir(90+360i/n);
            freelabel("$V_" & char(97+i) & "$", z[i], origin);
        endfor;
        for i = 0 upto n-3: draw z[i]-- z[i+2]; endfor
        draw z[n-2]--z0; draw z[n-1]--z1;
        drawoptions(withpen pencircle scaled 3bp withcolor red);
        for i = 0 upto n-1: drawdot z[i]; endfor
    endfig;
\end{mplibcode}
\end{document}

n=5:

enter image description here

n = 9:

enter image description here

4

A PSTricks solulution just for either comparison or fun purposes. For every TikZ solution there must be at least one solution in PSTricks, but the converse is not necessarily true.

\documentclass[pstricks]{standalone}
\usepackage{pst-plot}
\def\xstar#1{%
\begin{pspicture}(-3,-3)(3,3)
    \degrees[#1]
    \curvepnodes[plotpoints=\numexpr#1+1]{0}{#1}{2 t PtoCrel}{A}
    \foreach \i[evaluate=\i as \j using {int(mod(\i+floor(#1/2-1/2),#1))}]
        in {0,...,\numexpr#1-1}{%
            \qdisk(A\i){2pt}
            \uput{2mm}[\i](A\i){\char\numexpr\i+65}
            \psline(A\i)(A\j)}
\end{pspicture}}

\begin{document}
\foreach \k in {4,5,...,12}{\xstar{\k}}
\end{document}

enter image description here

2
  • 1
    Btw, the last theorem of Sandy's int(1+mod(int(\i+(#1+1)/2-1)-1,#1)) is awesome! Apr 13 at 13:39
  • 1
    +1 for PSTricks code... Apr 13 at 14:29
3

A shortcode with pstricks:

    \documentclass[border=10pt, svgnames]{standalone}
    \usepackage{pst-poly}

    \begin{document}

    \begin{pspicture}(-2,-2)(2,2)
    \psset{unit = 2cm, linejoin=1, PstPicture=false}
    \everypsbox{\scriptsize\emph{}}
    \PstPolygon[PolyNbSides=5, PolyOffset = 2,PolyRotation =18, linecolor=LightSteelBlue]
    \foreach \i/\angle/\s in{1/90/u, 2/162/l, 3/234/l, 4/306/r, 5/378/r}{\uput{3pt}[\s](1;\angle){\color{LightSteelBlue}$\i$}}
    \end{pspicture}

    \end{document}

enter image description here

2
  • OP wants to remove the circle
    – Black Mild
    Apr 11 at 21:20
  • 1
    @BlackMild: I didn't notice that the question hwas modified. I'll change my answer accordingly in a moment.
    – Bernard
    Apr 11 at 21:24
2

If you know how to do the math, you can make this with the commands for just lines and circles using the tikz package.

\documentclass{article}
\usepackage{tikz}

\begin{tikzpicture}
\draw (0,0) -- (5,0);
\draw (0.96,-2.94) -- (5,0);
\draw (0.96,-2.94) -- (2.51,1.81);
\draw (2.51,1.81) -- (4,-2.94);
\draw (0,0) -- (4,-2.94);
\filldraw[black] (0,0) circle (2pt) node[anchor=south]{0,0};
\filldraw[black] (5,0) circle (2pt) node[anchor=south]{5,0};
\filldraw[black] (0.96,-2.94) circle (2pt) node[anchor=north]{0.96,-2.94};
\filldraw[black] (2.51,1.81) circle (2pt) node[anchor=south]{2.51,1.81};
\filldraw[black] (4,-2.94) circle (2pt) node[anchor=north]{4,-2.94};
\end{tikzpicture}

\end{document}

enter image description here

(The coordinates I used don't make a perfect star because I took the liberty to do a bit of rounding when doing the calculations.)

EDIT: You can also simplify the solution above into a single line for actually drawing out the star instead of five.

\documentclass{article}
\usepackage{tikz}

\begin{tikzpicture}
\draw (0,0) -- (5,0) -- (0.96,-2.94) -- (2.51, 1.81) -- 
(4.04,-2.94) -- (0,0);
\filldraw[black] (0,0) circle (2pt) node[anchor=south]{0,0};
\filldraw[black] (5,0) circle (2pt) node[anchor=south]{5,0};
\filldraw[black] (0.96,-2.94) circle (2pt) node[anchor=north]{0.96,-2.94};
\filldraw[black] (2.51,1.81) circle (2pt) node[anchor=south]{2.51,1.81};
\filldraw[black] (4,-2.94) circle (2pt) node[anchor=north]{4,-2.94};
\end{tikzpicture}

\end{document}

And you can do it this way as well.

\begin{tikzpicture}
\tikzstyle{circ} = [circle, fill=black, radius=2pt]
\draw (0,0) -- (5,0) -- (0.96,-2.94) -- (2.51, 1.81) -- (4.04,-2.94) -- (0,0);
\path 
node at (0,0) [circ, label={above:0,0}]{} 
node at (5,0) [circ, label={above:5,0}]{} 
node at (0.96,-2.94)[circ, label={below:0.96,-2.94}]{} 
node at (2.51,1.81)[circ,label={above:2.51,1.81}]{} 
node at (4.04,-2.94)[circ,label={below:4.04,-2.94}]{};
\end{tikzpicture}
2

Assuming we only use 26 letters from A to Z. Refactoring Sandy G's answer such that we no longer need to manually enumerate the alphabetical node labels.

\documentclass[tikz,border=\dimexpr355pt/113\relax]{standalone}


\newcommand{\xstar}[2][1]{\begin{tikzpicture}
\foreach \i[evaluate=\i as \j using (\i-1)/#2*360+90] in {1,...,#2} {
    \node[inner sep=0pt] at (\j:#1)(p\i){};
    \node at (\j:(#1+.25){\char\numexpr\i+64\relax};}
\foreach \i[evaluate=\i as \j using {int(mod(\i+floor(#1/2-1/2),#1))}] in {1,...,#2}{
\draw[line cap=round] (p\i.center)--(p\j.center);}
\end{tikzpicture}}

\begin{document}
\xstar{5}
\xstar[2]{21}
\end{document}

enter image description here

enter image description here

2
1

A SkiaSharp solution just for fun!

using CSharpMath.SkiaSharp;
using SkiaSharp;
using System.Diagnostics;
using static System.MathF;

class Diagram
{
    const float scale = SKDocument.DefaultRasterDpi / 2.54f; // dots per cm

    static float PtToCm(float pt) => pt / scale;

    static readonly SKPaint stroke = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.Black,
        StrokeCap = SKStrokeCap.Round,
        IsAntialias = true,
        StrokeWidth = PtToCm(2)
    };

    static readonly SKPaint fill = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = SKColors.Black
    };

    static readonly SKRect domain = new SKRect(-3.5f, 3.5f, 3.5f, -3.5f);

    static readonly float width = domain.Width * scale;
    static readonly float height = -domain.Height * scale;

    static readonly float r = 2.5f;
    static readonly int n = 26; // max 26
    static readonly float di = 2 * PI / n;
    static readonly int s = (int)Floor((n - 1) / 2f);

    public static void Generate(string filename)
    {
        using (var stream = new SKFileWStream($"{filename}.pdf"))
        using (var document = SKDocument.CreatePdf(stream))
        using (var canvas = document.BeginPage(width, height))
        {
            canvas.Scale(scale, -scale);
            canvas.Translate(-domain.Left, -domain.Top);

            SKPoint[] points = Enumerable
                                    .Range(0, n)
                                    .Select(i => new SKPoint(r * Cos(i * di), r * Sin(i * di)))
                                    .ToArray();

            for (int i = 0; i < n; ++i)
            {
                int j = (s + i) % n;
                canvas.DrawCircle(points[i], PtToCm(2.5f), fill);
                canvas.DrawLine(points[i], points[j], stroke);

                MathPainterExtension.Painter.FontSize = PtToCm(12f);
                canvas.Draw($"{(char)(i + 65)}", points[i].X * 1.2f, points[i].Y * 1.2f);
            }

            document.EndPage();
        }
    }
}


public static class MathPainterExtension
{
    public static MathPainter Painter { get; } = new MathPainter();

    public static void Draw(this SKCanvas canvas, string str, float x, float y, float angleRad = 0f)
    {
        Painter.LaTeX = str;
        var rect = Painter.Measure();

        canvas.Save();
        canvas.Scale(1, -1);
        canvas.RotateRadians(-angleRad, x, -y);
        canvas.Translate(-rect.Width / 2, rect.Height / 2);
        Painter.Draw(canvas, x, -y);
        canvas.Restore();
    }
}

class Invoker
{
    static void Main()
    {
        string filename = "StarOfDavid";
        Diagram.Generate(filename);

        // convert to PNG with ImageMagick
        using (Process p = new Process())
        {
            p.StartInfo.FileName = "magick";
            p.StartInfo.Arguments = $"convert -compose copy -bordercolor red -border 2x2 -density 200 -alpha remove {filename}.pdf {filename}.png";
            p.Start();
        }
    }
}

enter image description here

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.