8

I have N points on a circle, I want to draw the intersection of the convex hulls of all sets of N-k consecutive points.

The points are not evenly spaced. The values of N and k (and the actual angles of each point) will change, so I'd rather not have a hard-coded solution.

Here is the best I've come up with. The silly way does exactly what I want, but it involves a lot of cut-and-paste every time. I don't understand why the second way fails; I've read that variables in \foreach loops don't quite behave as variables (I think), but I can't figure out a way around this.

\documentclass{article}
\usepackage{tikz}


\begin{document}

\begin{tikzpicture}[every node/.style={draw,inner sep=0mm}]

  \def\rad{5cm}
  \def\k{2}
  \def\N{6}


  \node (x1) at (15:\rad) {} ;
  \node (x2) at (45:\rad) {} ;
  \node (x3) at (90:\rad) {} ;
  \node (x4) at (120:\rad) {} ;
  \node (x5) at (210:\rad) {} ;
  \node (x6) at (270:\rad) {} ;


  %%% draw all the lines from xi to x(i+k)
  \foreach \i in {1,2,3,4,5,6} {
    \pgfmathtruncatemacro{\j}{1+mod(\i-1+\k,6)}
    \draw (x\i) -- (x\j) ;
  }


  %%% draw the intersection of all convex hulls of 5 consecutive points among the six
  %%% this is a silly way
  \clip (x1.center) -- (x2.center) -- (x3.center) -- (x4.center) -- (x5.center) -- cycle ;
  \clip (x2.center) -- (x3.center) -- (x4.center) -- (x5.center) -- (x6.center) -- cycle ;
  \clip (x3.center) -- (x4.center) -- (x5.center) -- (x6.center) -- (x1.center) -- cycle ;
  \clip (x4.center) -- (x5.center) -- (x6.center) -- (x1.center) -- (x2.center) -- cycle ;
  \clip (x5.center) -- (x6.center) -- (x1.center) -- (x2.center) -- (x3.center) -- cycle ;
  \fill (x6.center) -- (x1.center) -- (x2.center) -- (x3.center) -- (x4.center) -- cycle ;



  %%% draw the intersection of all convex hulls of N-k+1 consecutive points among the N
  %%% this is the code I think should work but doesn't
  %%% error message: ! Package tikz Error: Giving up on this path. Did you forget a semicolon?.
  \foreach \a in {1,...,\N}{
    \pgfmathsetmacro{\b}{1+mod(\a+\k,\N)}
    \draw (x\a) -- (x\b)
    \foreach \x in {\k,...,\N} {
      \pgfmathtruncatemacro{\xp}{1+mod(\a+\x-1,\N)}
      \pgfmathtruncatemacro{\xq}{1+mod(\a+\x,\N)}
      (x-\xp) -- (x-\xq)
    } ;
  }

\end{tikzpicture}


\end{document}

1 Answer 1

5

You need to complete a full, valid-syntax path at each spin of foreach. Also you can't simply do calculations right away when it is parsing the path commands. You need to bury them inside \pgfextra{} to pause the parsing and do other things.

So only change required here is below;

  \foreach \a in {1,...,\N}{
    \draw\pgfextra{\pgfmathsetmacro{\b}{1+mod(\a+\k,\N)}}
     (x\a) -- (x\b)
    \foreach \x in {\k,...,\N} {
      \pgfextra{\pgfmathtruncatemacro{\xp}{1+mod(\a+\x-1,\N)}
      \pgfmathtruncatemacro{\xq}{1+mod(\a+\x,\N)}}
      (x\xp) -- (x\xq)
    };
  }

enter image description here

I don't know if this is the intended result though.

2
  • The \pgfextra{} did the trick. (My indexing was wrong, and I needed to \clip and \fill, but that's my bad.) Aug 10, 2014 at 7:39
  • I guess \pgfextra{} isn't completely ignored when parsing for the path... For instance, \pgfextra{...}\draw (x\a) -- (x\b) does not seem to work. This isn't really a problem, but strikes me as odd. Aug 10, 2014 at 7:42

You must log in to answer this question.

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