2

Here's the simplest file I can think of which demonstrates my problem: I simply want to draw two circles, half filled:

\documentclass{article}

\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
  \foreach \x in {(0,0), (2,0)}
  {
    \draw \x circle[radius = 1];
    \begin{scope}[shift = \x]
      \draw[clip] (0,0) circle[radius = 1];
      \fill[black!50] (-1,-1) rectangle (1,0);
    \end{scope};
  }  
\end{tikzpicture}

\end{document}

As you can see if you run this, only the first circle is half filled. And I get a lot of errors:

Missing character: There is no ( in font nullfont!
Missing character: There is no 0 in font nullfont!
Missing character: There is no , in font nullfont!
Missing character: There is no 0 in font nullfont!
Missing character: There is no ) in font nullfont!

I'm a bit mystified by this, as I've never had this sort of error before.

I should say that although this particular problem could be solved easily by other means, it is really the simplest case of a more general diagram, which will consist (I hope) of lots of circles all filled to different depths.

I've tried putting brackets around \x; I've tried leaving out the shift parameter and using coordinate transformations, as in

\fill[black!50] \x + (-1,-1) rectangle \x + (1,0);

but that doesn't work either. (In fact the latter is even worse, as it only gives me the first circle one quarter filled.)

Any advice would be very warmly received!

2
  • You need \x to be expanded: \begin{scope}[shift/.expanded = \x]. Same problem and solution as Q643948. With your last snippet, you could just use relative coordinates: \fill[black!50] \x ++ (-1,-1) rectangle + (2,0); Nov 27, 2023 at 10:14
  • No ; after \end{scope} by the way. Nov 27, 2023 at 10:21

3 Answers 3

4

No image added, so I try this one:

enter image description here

Code:

\documentclass{article}

\usepackage{tikz}

\begin{document}
    
    \begin{tikzpicture}
        \foreach \x in {0,2}
        {
            \draw (\x,0) circle(1);
            \fill (\x+1,0) arc(0:-180:1);
        }  
    \end{tikzpicture}
    
\end{document}
3

Code

\documentclass[tikz]{standalone}
%\documentclass{article}
%\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\foreach \x in {(0,0), (2,0)}{
  \tikzset{shift/.expanded = \x} % https://tex.stackexchange.com/a/655530/16595
  \begin{scope}
    \clip (0,0) circle[radius = 1];
    \fill[black!50] (-1,-1) rectangle (1,0);
  \end{scope}
  \draw (0,0) circle[radius = 1];
}
\end{tikzpicture}

\tikz
  \foreach \x in {(0,0), (2,0)}
    \draw \x circle[radius=1] [
      path picture={
        \fill[black!50] (path picture bounding box.south west)
              rectangle (path picture bounding box.east);}];

\tikz
  \foreach \x in {(0,0), (2,0)}
    \draw[shift=\x] (0,0) circle[radius=1] [
      path picture={\fill[black!50] (-1,-1) rectangle +(2,1);}];
\end{document}
3

You need to take care of the different ways TikZ parses and expands the input. It seems that in different contexts, things are not expanded as might be expected.

For example, while this works (thanks to Qrrbrbirlbel for the hint):

\documentclass[border=10pt]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
  \foreach \x in {(0,0), (2,0)} {
    \begin{scope}
        \draw[clip] \x circle[radius = 1];
        \fill[black!50] \x ++(-1,-1) rectangle +(2,1);
    \end{scope}
  }  
\end{tikzpicture}
\end{document}

This does not:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
  \foreach \x in {(0,0), (2,0)} {
    \coordinate (x) at \x;
    \begin{scope}[shift = {(x)}]
        \draw[clip] (0,0) circle[radius = 1];
        \fill[black!50] (-1,-1) rectangle (1,0);
    \end{scope}
  }  
\end{tikzpicture}
\end{document}

Nor does this:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
  \foreach \x in {(0,0), (2,0)} {
    \coordinate (x) at \x;
    \draw (x) circle[radius = 1];
  }  
\end{tikzpicture}
\end{document}

So, the safest way to do this is probably still like this:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
  \foreach \x in {{0,0}, {2,0}} {
    \draw (\x) circle[radius = 1];
    \begin{scope}[shift = {(\x)}]
      \draw[clip] (0,0) circle[radius = 1];
      \fill[black!50] (-1,-1) rectangle (1,0);
    \end{scope}
  }  
\end{tikzpicture}
\end{document}

enter image description here

It seems that while at as keyword (as in \coordinate (x) at ...) only likes explicit coordinates, using at as option should work here (at least with a current version of TikZ). So a variation of the above would be:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
  \foreach \x in {(0,0), (2,0)} {
    \coordinate[at=\x] (x);
    \begin{scope}[shift = {(x)}]
        \draw[clip] (0,0) circle[radius = 1];
        \fill[black!50] (-1,-1) rectangle (1,0);
    \end{scope}
  }  
\end{tikzpicture}
\end{document}
6
  • 1
    Many thanks - so that was my error! I've used lists of coordinates before, but here, as you point out, there are subtleties of parsing to be considered. That works perfectly.
    – Alasdair
    Nov 27, 2023 at 7:48
  • Well, I am not fully sure about the parsing mechanism, but I think the problem is that, on the one hand, you need to mask the comma, so you need to write {(0,0)}, but you can't say \coordinate (c) at {(0,0)}. Nov 27, 2023 at 7:50
  • 1
    You don't need to mask a (x,y) notation as the first variable for a PGFFor list, it detects the ( and grabs until the next ). At least with an uptodate PGF. (Of course, your code here doesn't have the ( anymore and then the {} are necessary.) The problem comes from the shift at the scope which doesn't try to expand the argument as it would on a path. The expansion counter isn't set up correctly. Nov 27, 2023 at 10:19
  • @Qrrbrbirlbel I see. I also discovered that the shift context somehow seems to parse things differently. I was able to pass (0,0) as \x to \coordinate (c) at \x;, but later on using (c) didn't really work. Nov 27, 2023 at 10:24
  • 1
    coordinate at … is a “quick” version of node[shape=coordinate] at … but doesn't parse the at part like a node. It requires explicit (…). Yes, TikZ can be finicky about things. It already expands a lot of things at various places but they haven't thought of everything. Nov 27, 2023 at 10:44

You must log in to answer this question.

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