2

I need a semicircle node centred at chord center. The positioning is achieved with the option anchor, but the external lines are still directed to center. Is it possible to direct lines to chord center as well?

MWE

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\usetikzlibrary{shapes.geometric}

\begin{tikzpicture}
\node [semicircle,draw,shape border rotate=180,anchor=chord center,outer sep=0,inner sep=0.2cm] (a) at (1,1) {};
\draw (0,0) -- (a);
\draw[densely dashed] (0,0) -- (1,1);
\end{tikzpicture}

\end{document}

enter image description here

8
  • with \draw (0,0) -- (a.north);
    – pascal974
    Mar 15, 2023 at 12:35
  • @pascal974 Yes, but in this case line will not be hidden behind the node.
    – Pygmalion
    Mar 15, 2023 at 12:37
  • if fill=whire is acceptable for you \node (a) at (1,1){}; \draw (0,0) -- (a); \node [semicircle,draw,shape border rotate=180,anchor=chord center,outer sep=0,inner sep=0.2cm,fill=white] at (a) {};
    – pascal974
    Mar 15, 2023 at 12:43
  • No, nodes usually only find the border point from the center anchor. In this case you should be able to use (a.225) instead. Anything more automatic will be a shape-dependent solution including some calculation. Alternatively, you could as hidden circle node with it's center at a.north and use that instead of a. Again, an automatic approach would have to figure out on which side of the semicircle the line needs to be connected to. Mar 15, 2023 at 12:46
  • @Qrrbrbirlbel The problem here is just an example, the actual angle I use is not 225 degrees.
    – Pygmalion
    Mar 15, 2023 at 12:48

4 Answers 4

5

Short of defining a new shape, here's a cheaty version with another circle node around it.

For this, I'll add the anchor semicircle center to the shape which always sits in the middle of the chord, independently of the outer sep.

This allows you to place the shape on the semicircle center without changing the outer seps.

Then we add another circle node that has the same (outer) radius as the semicircle. This gets the same name as the semicircle but with a ' added.

Technically, we could extract the radius from the shape itself but the through library makes it very easy. (It measures the distance between the at and the through point and sets that as the minimum size of the node.)

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{shapes.geometric, through}
\makeatletter
\pgfutil@namedef{pgf@anchor@semicircle@semicircle center}{%
  \pgfpointadd{\pgf@sh@reanchor{semicircle}{chord center}}{%
    \installsemicircleparameters\pgfpointpolar{\rotate+90}{\outersep}}}
\makeatother
\tikzset{
  circle around semi/.style={
    append after command={[every node/.code=]%
    node[at=(\tikzlastnode.semicircle center),
    circle through=(\tikzlastnode.apex), overlay, 
    anchor=center, name=\tikzlastnode', inner sep=+0pt, outer sep=+0pt,
    path only]{}}}}
\begin{document}

\begin{tikzpicture}[ultra thick]
\node [
  semicircle, circle around semi, draw,
  shape border rotate=180,
  anchor=semicircle center,
  inner sep=0.2cm
] (a) at (1,1) {};
\draw[red] (0,0) -- (a');
\end{tikzpicture}
\tikz\draw[ultra thick]
  (0,0) .. controls +(30:1) and +(135:2) .. (2,2)
  foreach[count=\i from 0, evaluate=\i as \c using \i/4*100]
    \pos in {.125, .333, .5, .75, .95}{
    node[fill=red!\c!blue, draw=blue!\c!red, fill, thin, sloped,
    semicircle, circle around semi, pos=\pos, anchor=semicircle center](@){}
    (@') foreach \ang in {0,15,...,359}{edge[thin] ++(\ang:.3)}
  };
\end{document}

Output

enter image description here

enter image description here

1
  • Good! This actually gave me an idea. I am simply drawing a named invisible circle and unnamed visible semicircle with the same minimum width (with inner sep = 0). It is less verbose and easier to maintain. After all, it appears only few times in the whole document. (And I actually understand what is going on :P)
    – Pygmalion
    Mar 15, 2023 at 17:43
4

Maybe clipping could work (but maybe not in your specific case, and positioning text inside the semicircle would need adjustment):

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

\begin{scope}
\clip (0.5,1) rectangle +(1,-1);
\node [circle, draw, outer sep=0, inner sep=0.25cm] (a) at (1,1) {};
\end{scope}

\draw[line cap=rect] (a.east) -- (a.west);
\draw[red] (0,0) -- (a);

\end{tikzpicture}
\end{document}

enter image description here

2

From my comment, we can work around the problem with \fill

The code

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
\colorlet{pagebackground}{yellow!10}
\pagecolor{pagebackground}
\begin{document}
\begin{tikzpicture}
  \coordinate (a) at (1,1);
  \draw [red](0,0) -- (a);
  \node [semicircle,draw,shape border rotate=180,anchor=chord center,outer sep=0cm,inner sep=0.2cm,fill=pagebackground] at (a) {};
\end{tikzpicture}
\end{document}

enter image description here

2

I always want to keep the code as simple as possible (KISS) and that I understand it and can actually maintain it. So based on @Qrrbrbirlbel's solution, I am going with this code:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\usetikzlibrary{shapes.geometric}

\newcommand{\semicircleup}[4]{%
\node[circle,outer sep=0pt,inner sep=0,minimum width=2*#3] (#1) at #2 {};
\node[semicircle,shape border rotate=180,anchor=chord center,outer sep=0pt,inner sep=0,minimum width=2*#3,#4] at (#1) {};
}

\begin{tikzpicture}
\semicircleup{a}{(1,1)}{0.5cm}{draw,fill=white}
\draw (0,0) -- (a);
\end{tikzpicture}

\end{document}

It draws a named invisible circle node (to crop the lines) and an unnamed visible semicircle node with the same minimum width (with inner sep=0).

Additional advantage (which is important to me) is that no additional library is used.

But I will still accept @Qrrbrbirlbel's answer as cudos for his idea.

You must log in to answer this question.

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