8

I want to generate a list called anglelist to generate a graph... the prefered command for me is \edef\anglelist{\fullanglelist} but gives me an error.

But using \edef\anglelist{\fullanglelist} and \edef\anglelist{\fixedlist} wont give me any error.

My Question is "Would you tell me how should I make \edef\anglelist{\fullanglelist} working?

Thanks, in advance. Following please have a look at the code I am talking about.

\documentclass[11pt]{article}
\usepackage{tikz}
\begin{document}

\newcount\nodes
\nodes=8

\newcount\hnodes
\hnodes=\nodes
\advance \hnodes by -1
\divide \hnodes by 2
%
\newcount\hnodesplus
\hnodesplus=\nodes
\advance \hnodesplus by 1
\divide \hnodesplus by 2
%
\newcount\initialstepsize
\initialstepsize=360
\divide \initialstepsize by \nodes
%
\newcount\initialremainder
\initialremainder=\initialstepsize
\multiply \initialremainder by -\nodes
\advance \initialremainder by 360
%
\newcount\hstep
\hstep=\initialstepsize
\divide \hstep by 2

\newcount\simplestep
\simplestep=\initialstepsize
\ifnum \initialremainder > 0%this makes angles a larger than expected. 
\advance \simplestep by 1
\fi



\def\fullanglelister{%
\newcount\tempa
\newcount\tempb
\tempa=0
\tempb=0
%
\loop
\the\tempa\relax
\advance\tempa by \initialstepsize
\advance\tempb by \initialremainder
\ifnum\tempb > \hnodes% usually chosen to be 0, (better to be) \hnodes, or \nodes 
\advance\tempa by 1
\advance\tempb by -\nodes
\fi
\ifnum \tempa < 360
,
\repeat}


\def\shortanglelister{0, \the\simplestep, ..., 359}
\def\fixedlist{0, 45, 90, 135, 180, 225, 270, 315}

\edef\anglelist{\shortanglelister}
%\edef\anglelist{\fullanglelister} % this one doesn't work!
%\edef\anglelist{\fixedlist} % but this works!

\begin{tikzpicture}
  \foreach \angle in \anglelist
\node[rectangle,draw=black!50] (\angle) at (\angle:2) {\angle};

\foreach \from in \anglelist
\foreach \to in \anglelist
\path (\from) edge [->,bend right=\the\hstep,looseness=0.8] (\to);
\end{tikzpicture}


\fullanglelister
\shortanglelister
\fixedlist

\end{document}
  • 2
    You've got a rather haphazard mix here of low level TeX primitive programming and TikZ! In particular, have you read up on expansion, for example tex.stackexchange.com/questions/451/…? You cannot perform assignments inside \edef. – Joseph Wright Sep 19 '16 at 10:32
  • 1
    Apart from the mistake of having \newcount\tempa and \newcount\tempb in the definition of \fullanglelister, you have to take into account that \edef only expands macros, but does no assignment. – egreg Sep 19 '16 at 10:32
  • 2
    @StevenB.Segletes No, in TeX you cannot perform assignments inside \edef or similar contexts. In LuaTeX things inside \directlua are different, and one might appeal to \csname ... \endcnsame making undefined control sequences into \relax for 'special effects', but that is not general. – Joseph Wright Sep 19 '16 at 10:43
  • 1
    You can use \foreach\x in {0,45,...,359} to get same list you are preparing with \fullanglelister; it's not clear why going the hard way for writing the full list. – egreg Sep 19 '16 at 10:44
  • 2
    clearly you can not use that command in an edef as it does not work by expansion, perhaps you should edit the question asking about what you actually want to do rather than about one possible way of doing it which can not work. Also you should not have \newcount inside the definition of \fullanglelister as you do not want to allocate new registers every time you use the command. – David Carlisle Sep 19 '16 at 11:24
5

If (for some reason) you want to expand the loop in an edef then you need to write it using expansion, not using assignments. The following code expands to

0, 45, 90, 135, 180, 225, 270, 315

as shown by the typeout line

B: 0, 45, 90, 135, 180, 225, 270, 315

on the console

\documentclass[11pt]{article}
\usepackage{tikz}
\begin{document}

\newcount\nodes
\nodes=8

\newcount\hnodes
\hnodes=\nodes
\advance \hnodes by -1
\divide \hnodes by 2
%
\newcount\hnodesplus
\hnodesplus=\nodes
\advance \hnodesplus by 1
\divide \hnodesplus by 2
%
\newcount\initialstepsize
\initialstepsize=360
\divide \initialstepsize by \nodes
%
\newcount\initialremainder
\initialremainder=\initialstepsize
\multiply \initialremainder by -\nodes
\advance \initialremainder by 360
%
\newcount\hstep
\hstep=\initialstepsize
\divide \hstep by 2

\newcount\simplestep
\simplestep=\initialstepsize
\ifnum \initialremainder > 0%this makes angles a larger than expected. 
\advance \simplestep by 1
\fi



\makeatletter
\def\fullanglelister{%
\expandafter\@gobble\romannumeral`\^^@%
\expandafter\zz\shortanglelister\relax}
\def\zz#1,#2,#3,#4\relax{%
\ifnum#1<\numexpr#4\relax
, \the\numexpr#1\relax
\expandafter\zz\the\numexpr#1+#2\relax,#2,#3,#4\relax
\fi}
\makeatother

\def\shortanglelister{0, \the\simplestep, ..., 359}
\def\fixedlist{0, 45, 90, 135, 180, 225, 270, 315}

\edef\anglelist{\shortanglelister}
\typeout{A:\anglelist}
\edef\anglelist{\fullanglelister} % this one does work!
\typeout{B:\anglelist}
%\edef\anglelist{\fixedlist} % but this works!

\begin{tikzpicture}
  \foreach \angle in \anglelist
\node[rectangle,draw=black!50] (\angle) at (\angle:2) {\angle};

\foreach \from in \anglelist
\foreach \to in \anglelist
\path (\from) edge [->,bend right=\the\hstep,looseness=0.8] (\to);
\end{tikzpicture}


\fullanglelister
\shortanglelister
\fixedlist

\end{document}
3

If you want integers to move toward a particular goal as evenly as possible, the best way is to recompute the step size at each iteration as the remaining distance divided by the number of remaining steps.

The usual practice is to place the result of \edef into a different macro than the one creating it. For example, the output of \pgfmathparse is put into \pgfmathresult, and \pgfmathsetmacro accepts the output macro name as an argument. This is the approach I took.

\documentclass[11pt]{article}
\usepackage{tikz}

\newcount\nodes% considering how infrequently this is used, a macro would suffice

\def\fullanglelister#1{% #1 = output macro name (global)
\bgroup% use local registers
  \count1=0 % angle
  \count2=\nodes% remaining steps
  \edef\temp{\the\count1}% output macro (local)
  \loop
    \count3=360 % compute step size (360-angle)/steps
    \advance \count3 by -\count1
    \divide \count3 by \count2
    \advance\count1 by \count3
    \advance\count2 by -1
    \edef\temp{\temp,\the\count1}%
  \ifnum \count2>1 \repeat
  \global\let#1\temp
\egroup}

\begin{document}

\nodes=8
\fullanglelister{\anglelist}%
\pgfmathsetmacro{\hstep}{360/\nodes}%

\begin{tikzpicture}
  \foreach \angle in \anglelist
\node[rectangle,draw=black!50] (\angle) at (\angle:2) {\angle};

\foreach \from in \anglelist {
  \foreach \to in \anglelist {
    \path (\from) edge [->,bend right=\hstep,looseness=0.8] (\to);}}
\end{tikzpicture}

\end{document}

demo

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.