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
    Commented Apr 11, 2022 at 19:53
  • @Andre Sure, you can embed in your tex file as a tikz picture or asy picture. See my update!
    – Black Mild
    Commented Apr 11, 2022 at 21:14
  • This is great. I will use your solution 2. Can you explain how \pgfmathparse and \pgfmathresult work?
    – Andre
    Commented Apr 12, 2022 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
    Commented Apr 12, 2022 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? Commented Apr 12, 2022 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
    Commented Apr 12, 2022 at 5:27
  • 1
    @Dr.ManuelKuehner: You can print, for example, A with \char 65. Commented Apr 13, 2022 at 7:30
  • 1
    I discovered another expression: int(mod(\i+floor(#1/2-1/2),#1)) Commented Apr 13, 2022 at 19:07
  • 1
    @TheCodeMocker Thanks for the follow-up. Commented Apr 13, 2022 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! Commented Apr 13, 2022 at 13:39
  • 1
    +1 for PSTricks code... Commented Apr 13, 2022 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
    Commented Apr 11, 2022 at 21:20
  • 1
    @BlackMild: I didn't notice that the question hwas modified. I'll change my answer accordingly in a moment.
    – Bernard
    Commented Apr 11, 2022 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
  • Where is your PSTricks's code? Commented Apr 13, 2022 at 9:03
  • The correct question is Where is your PSTricks' code?. Commented Apr 13, 2022 at 10:06
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

You must log in to answer this question.

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