1

I have an image where I'd like to draw arrows between nodes where the arrows are all "on the same circle". I can achieve what I want by hand as follows:

\documentclass{standalone}

\usepackage{tikz} \usetikzlibrary{shapes} \begin{document} \begin{tikzpicture}[ultra thick, -stealth] \node[circle,fill] (a) at (0: 1) {}; \noderectangle,minimum width=1cm,fill at (120: 1) {}; \noderectangle,minimum height=1cm,fill at (240: 1) {}; \draw[dashed] (85: 1) arc (85: 30: 1) ; \draw (330:1) arc (330: 280:1) ; \draw[dashed] (200:1) arc (200: 140:1); \end{tikzpicture} \end{document}

But if my nodes are different shapes and sizes, I have to find coordinates that work by hand. What I'd really like to do, is find where the edges of the node intersect the circle and draw the arcs using those edges. Is there an automatic way to do this? This answer is a partial solution, but it seems like I'd still have to pick the arcs and shorten lengths by hand...

The actual use case is that the nodes will contain pictures of different aspect ratios. I've approximated the problem using some akward shaped nodes.

Seamus
  • 73,242
  • 2
    Could you modify your code, so that the nodes has "different shapes and sizes"? -it would make it a lot easier to test a solution. – hpekristiansen Aug 28 '20 at 11:16
  • 2
    In your code, the nodes are equidistant and form an equilateral triangle. Does this always have to be the case? – AndréC Aug 28 '20 at 11:18
  • @AndréC no. I'm interested in a general solution. But they'll always be given by polar coordinates at the same radius. – Seamus Aug 28 '20 at 13:31
  • @hpekristiansen that's a good idea, I'll do that next time I'm at my desk. – Seamus Aug 28 '20 at 13:33
  • As I know, it is impossible to do such thing automatically with different shapes because there is no common way to calculate the intersection of the shape border and the arc path. – ZhiyuanLck Aug 28 '20 at 16:56

1 Answers1

1

Heiko Oberdiek rules!!!! --

https://tex.stackexchange.com/a/250270/197451

enter image description here

\documentclass{article}

\usepackage{tikz} \usetikzlibrary{bending}

\begin{document} \begin{tikzpicture}[ ->,
thick, main node/.style={circle, fill=blue!20, draw}, ] \newcommand{\MainNum}{5} \newcommand{\MainRadius}{1.5cm} \newcommand*{\MainStartAngle}{90}

% Print main nodes, node names: p1, p2, ...
\path
(0, 0) coordinate (M)
\foreach \t [count=\i] in {A, Hello\\World, 3, foobar, $\cdot$} {
    +({\i-1)*360/\MainNum + \MainStartAngle}:\MainRadius)
    node[main node, align=center] (p\i) {\t}
}
;  

% Calculate the angle between the equal sides of the triangle
% with side length \MainRadius, \MainRadius and radius of circle node
% Result is stored in \p1-angle, \p2-angle, ...
\foreach \i in {1, ..., \MainNum} {
    \pgfextracty{\dimen0 }{\pgfpointanchor{p\i}{north}} 
    \pgfextracty{\dimen2 }{\pgfpointanchor{p\i}{center}}
    \dimen0=\dimexpr\dimen2 - \dimen0\relax 
    \ifdim\dimen0<0pt \dimen0 = -\dimen0 \fi
    \pgfmathparse{2*asin(\the\dimen0/\MainRadius/2)}
    \global\expandafter\let\csname p\i-angle\endcsname\pgfmathresult
}

% Draw the arrow arcs
\foreach \i [evaluate=\i as \nexti using {int(mod(\i, \MainNum)+1}]
in {1, ..., \MainNum} {  
    \pgfmathsetmacro\StartAngle{   
        (\i-1)*360/\MainNum + \MainStartAngle
        + \csname p\i-angle\endcsname
    }
    \pgfmathsetmacro\EndAngle{
        (\nexti-1)*360/\MainNum + \MainStartAngle
        - \csname p\nexti-angle\endcsname
    }
    \ifdim\EndAngle pt < \StartAngle pt
    \pgfmathsetmacro\EndAngle{\EndAngle + 360}
    \fi
    \draw
    (M) ++(\StartAngle:\MainRadius)
    arc[start angle=\StartAngle, end angle=\EndAngle, radius=\MainRadius]
    ;
}
\end{tikzpicture}

\end{document}

js bibra
  • 21,280