15

I want to put an arrow head at the middle of an arc. Unfortunately, ArrowInside is not available for \psarc. The possible way is to construct it with 2 arcs as follows. Leaving arcsepB with its default value will produce a weird effect, that is why I have to set arcsepB to a negative length.

I hate a trial and error approach to get the best value for it. I believe there is a formula to exactly specify the maximum value for it.

enter image description here

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\psset{linewidth=5\pslinewidth}
\begin{document}
\multido{\n=0.0+-0.5}{30}{%
\begin{pspicture}(3,3)
\psarc[arrowscale=2,arcsepB=\n pt]{->}(0,0){3}{0}{45}
\psarc(0,0){3}{45}{90}
\rput(1.5,1.5){\n pt}
\end{pspicture}}
\end{document}

Is there a formula to determine the maximum value arcsepB such that the arrow head looks best?

The following is taken from PSTricks documentation (use texdoc pstricks), it might be useful for you.

enter image description here

With an elementary geometry (as opposed to differential geometry or topology), I should find the formula.

6
  • I think you have to take back the arrow head and let the line join close the curve so I would go with a negative inset that is equal to -arrowlength. Otherwise the arrow head would be placed a little rotated since it would be trying to follow the curve as barely visible in your another fantastic animation. (It's turning slightly CCW which is more than the tangent angle). That might on the other hand turn it wrongly in the other direction.
    – percusse
    Oct 19, 2012 at 13:58
  • @percusse: it will be easier to understand if you provide me with a real code as opposed the sentences. Oct 19, 2012 at 15:28
  • Hmmm, it seems my bounty to be too small to stimulate you.... I will increase it for the next bounty. Oct 25, 2012 at 4:53
  • No, I just don't know enough PSTricks.
    – percusse
    Oct 25, 2012 at 8:43
  • In fact you're just looking for a formula to calculate the extra length for the arc? As far as i know arrowlength=(length of arrow)/(width of arrow)=(extra length of arc)/(width of arc)... so extra length of arc = (width of arc)*arrowlength? In this case 5\pslinewidth*1.4, so 7\pslinewidth?
    – long tom
    Oct 25, 2012 at 20:36

3 Answers 3

5
+200

I have three solutions ludicrous attempts for you:

  1. a graphical/geometrical which I actually think is right,
  2. a mathematically “precise” equation (probably not correct),
  3. a approximation of the second point (surely wrong).

1. The geometry

enter image description here

The solution seems near, we only have to solve for t1.

Why is arcsepB the way I sketched it? The PSTricks manual states:

angleB is adjusted so that the arc would just touch a line of width dim that extended from the center of the arc in the direction of angleB.

2. The “precise” equation

I used the vector from A to B to get an equation that is only expressed in terms of t1. This is what I got:

enter image description here

It looks good, but even a numerical approximation to solve this equation didn’t yield any results. (A previous version of this equation did however, but did not correspond to TikZ’ result.)

3. The approximation

The following steps required some trigonometric approximations that are only valid for small angles of t1, which is true for big arrows and relevantly small line widths (the sketch is out of proportions).

I finally got to a simple quadratic equation that is solvable but—in this case—not in ℝ. (The radicand is lower than zero.)

enter image description here

The whole document and derivation

\documentclass{article}
\usepackage{mathtools,tikz}
\newcommand*{\sub}[1]{_{\textrm{#1}}}
\newcommand*{\vect}[1]{\vec{#1}}
\setlength\delimitershortfall{0pt}
\usetikzlibrary{intersections,calc,decorations.pathreplacing,fpu}
\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

% some lengths
\newlength{\dimRadius}
\newlength{\dimLinewidth}
\newlength{\dimArrowsize}
\newlength{\arWidth}
\newlength{\arLength}
\newlength{\arInset}

% PSTricks variables
\pgfmathsetlength\dimRadius{.5cm}%                    see MWE
\pgfmathsetlength\dimLinewidth{4pt}%                  see MWE, 5 * \pstlinewidth = 5 * .8pt
\pgfmathsetlength\dimArrowsize{1.5pt}%                see PSTricks manual
\newcommand*{\numArrowsize}{2}%                       see PSTricks manual
\newcommand*{\numArrowlength}{1.4}%                   see PSTricks manual
\newcommand*{\numArrowinset}{0.4}%                    see PSTricks manual
\newcommand*{\numArrowscale}{2}%                      see MWE
\newcommand*{\angStart}{0}
\newcommand*{\angEnd}{180}
% set random
\newcommand*{\angUntip}{50}

% result
\newlength{\arcsepB}
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\pgfmathsetlength\arWidth{\numArrowscale*(\numArrowsize*\dimLinewidth+\dimArrowsize)}% see PSTricks manual
\pgfmathsetlength\arLength{\arWidth*\numArrowlength}% see PSTricks manual
\pgfmathsetlength\arInset{\arLength*\numArrowinset}%  see PSTricks manual
\pgfmathsetmacro\angTip{\angUntip+2*asin((\arLength-\arInset)/(2*\dimRadius))}
\pgfmathsetmacro\arDirection{atan2(cos(\angTip)-cos(\angUntip),(sin(\angTip)-sin(\angUntip)))}
\pgfmathsetmacro\angBeta{atan(.5*\arWidth/\arLength)}
\newcommand*{\tikzScale}{10}

\usepackage{cleveref}
\makeatletter
\newcommand*{\strippt}[1]{\strip@pt#1}
\makeatother
\newcommand*{\pt}{\,\textrm{pt}}
\newcommand*{\wline}{w\sub{line}}
\newcommand*{\larrow}{l\sub{arrow}}
\newcommand*{\iarrow}{i\sub{arrow}}
\begin{document}
\begin{figure}\centering
\begin{tikzpicture}[thick,scale=\tikzScale]
\fill[black!20] (\angStart:\dimRadius+\dimLinewidth/2) arc[radius = \dimRadius+\dimLinewidth/2, start angle=\angStart, end angle=\angEnd] --
              (\angEnd:\dimRadius-\dimLinewidth/2) arc[radius = \dimRadius-\dimLinewidth/2, start angle=\angEnd, end angle=\angStart] -- cycle;

\draw[name path=middle line, thin, dashdotted] (0:\dimRadius)                 arc[radius = \dimRadius,                 start angle=\angStart, end angle=\angEnd];
\draw[name path=outer line,  thin]             (0:\dimRadius+\dimLinewidth/2) arc[radius = \dimRadius+\dimLinewidth/2, start angle=\angStart, end angle=\angEnd];
\draw[name path=inner line,  thin]             (0:\dimRadius-\dimLinewidth/2) arc[radius = \dimRadius-\dimLinewidth/2, start angle=\angStart, end angle=\angEnd];

\begin{pgfinterruptboundingbox}
\draw[name path global=arrow, blue, fill=blue, fill opacity=.2, line join=round]
    (\angUntip:\dimRadius) coordinate (D) -- (\angTip:\dimRadius) coordinate (A) -- ++ (
        {\arDirection-(180-\angBeta)}:{sqrt((\arWidth/2)^2+(\arLength)^2)}
    ) -- cycle;
\end{pgfinterruptboundingbox}
\fill[name intersections={of=arrow and outer line}, red] (intersection-1) coordinate (B);
\path[name path=radius to B] (B) -- (0,0);
\fill[name intersections={of=radius to B and middle line}, red] (intersection-1) coordinate (C);
\draw[gray] (B) -- (C);% half linewidth

\begin{pgfinterruptboundingbox}
\draw[name path global=continuous of C, ultra thin] let \p1=(C), \n1={atan2(\x1,\y1)} in (C) -- +(\n1+90:1) \pgfextra{\xdef\angArcEnd{\n1}};
\draw[name path global=rect of A,       ultra thin] (A) -- + (\angArcEnd:1);
\end{pgfinterruptboundingbox}
\fill[name intersections={of=continuous of C and rect of A}, red] (intersection-1) coordinate (E);

\draw [green] let \p1 = (C), \p2 = (E), \n1 = {veclen(\x2-\x1,\y2-\y1)} in 
    \pgfextra{\global\arcsepB=\n1}
    (C) -- (E);
\pgfmathsetmacro\arcsepBwithoutpt{\arcsepB}

\draw [green,opacity=.5] (A) -- + (\angArcEnd-90:\arcsepB);
\draw[gray] (0,0) -- (\angStart:\dimRadius)
            (0,0) -- (C)
            (0,0) -- (A)
            (0,0) -- (D);

\draw (\angStart:.31\dimRadius) arc [radius=.31\dimRadius, start angle=\angStart, end angle=\angArcEnd] node at ({(\angArcEnd+\angStart)/2}:.2\dimRadius) {\(t_0\)};
\draw (\angArcEnd:.3\dimRadius) arc [radius=.3\dimRadius, start angle=\angArcEnd, end angle=\angTip] node at ({(\angTip+\angArcEnd)/2}:.2\dimRadius) {\(t_1\)};
\draw ($(A)!.3\dimRadius!(D)$) arc [radius=.3\dimRadius, start angle=\arDirection-180, end angle=\arDirection-(180-\angBeta)] node[shift={({(\arDirection-180+\arDirection-(180-\angBeta))/2}:.2\dimRadius*\tikzScale)}] at (A) {\(\beta\)};
\draw let \p1 = (D), \n1={atan2(\x1,\y1)} in
      (\n1:.33\dimRadius) arc [radius=.33\dimRadius, start angle=\n1, end angle=\angArcEnd] node at ({(\n1+\angArcEnd)/2}:.4\dimRadius) {\(t_2\)};
\draw (\angUntip:.7\dimRadius) arc[radius=.3\dimRadius, start angle=\angUntip+180, end angle=\arDirection] node[shift={({(\angUntip+180+\arDirection)/2}:.2\dimRadius*\tikzScale)}] at (D) {$\alpha$};
\draw (D) -- + (0:.35\dimRadius);
\draw ([xshift=.3\dimRadius]D) arc[radius=.3\dimRadius, start angle=0, end angle=\arDirection] node[shift={(\arDirection/2:.2\dimRadius*\tikzScale)}] at (D) {$\gamma$};
\tikzset{decoration=brace}
\draw[decorate] (D) -- node[sloped,below] {\(\larrow-\iarrow\)} (A);
\draw[decorate] (E) -- node[sloped,above] {\(\mathtt{arcsepB} = \pgfmathprintnumber{\arcsepBwithoutpt}\,\textrm{pt} \)} (C);



\foreach \p/\pos in {A/left,B/above,C/below,D/below,E/left} {
    \fill[red] (\p) circle (.5pt/\tikzScale);
%   \begin{pgfonlayer}{background}
        \expandafter\node\expandafter[\pos,red!75!black] (n\p) at (\p) {$\p$};
%   \end{pgfonlayer}
}
%\node at (90:1cm) {\the\dimLinewidth};
\end{tikzpicture}
\pgfmathsetmacro\radBeta{\angBeta/180*pi}
\pgfmathsetmacro\lminusi{\the\arLength-\the\arInset}
\caption{We're looking for $t_1$. $\beta = \radBeta\,\textrm{rad}$, $\wline = \strippt{\dimLinewidth}\pt$, $r = \strippt{\dimRadius}\pt$, $\larrow = \strippt{\arLength}\pt$, $\iarrow = \strippt{\arInset}\pt$}
\end{figure}

\section{Our Goal}
First things first, $\mathtt{arcsepB}$ can be calculated by
\begin{equation}
    \mathtt{arcsepB} = r\sin t_1 \label{eq:goal}
\end{equation}

\section{What do we know?}
But before we begin, let us define some points:
\begin{subequations}\label{eq:start}
\begin{align}
 \vect{A} & = r \begin{pmatrix}
                    \cos(t_0+t_1) \\
                    \sin(t_0+t_1)
                \end{pmatrix}                   \\
 \vect{B} & = \left(r+\frac{\wline}2\right) \begin{pmatrix}
                                                     \cos t_0 \\
                                                     \sin t_0
                                                 \end{pmatrix}   \\
 \vect{D} & = r \begin{pmatrix}
                    \cos(t_0-t_2) \\
                    \sin(t_0-t_2)
                \end{pmatrix}
\end{align}
\end{subequations}

Geometry does also teach us:
\begin{subequations}\label{eq:aux}
\begin{align}\begin{split}
    l\sub{arrow} - \iarrow & = 2 r \sin(t_1 + t_2) \\
    t_2 & = \arcsin \left(\frac{\larrow-\iarrow}{2r}\right) - t_1 \label{eq:aux:t2} \end{split}\\
    \tan \beta & =  \frac{w\sub{arrow}}{2 \, \larrow} \label{eq:aux:beta}
\end{align}
\end{subequations}

The angle $\alpha$ can be calculated by
\begin{equation}\label{eq:alpha}
    \alpha = \frac{\pi-(t_1+t_2)}{2}.
\end{equation}

The direction of the arrow $\gamma$ (from $\vect{D}$ to $\vect{A}$) and $\gamma'$ (from $\vect{A}$ to $\vect{D}$) is
\begin{subequations}
\begin{align}\label{eq:gamma}
        \gamma & = t_0 - t_2 + \pi - \alpha \\[\jot] \shortintertext{and}
    \begin{split}
        \gamma' & = \gamma \pm \pi = t_0 - t_2 - \alpha \\
                & = t_0 + \frac{t_1-t_2}{2} - \frac{\pi}{2}
    \end{split}
\end{align}
\end{subequations}

\section{Approach}
How do we get from $\vect{A}$ to $\vect{B}$?
\begin{equation}\label{eq:AtoB}
    \vect{B} = \vect{A} + \tau \begin{pmatrix} \cos(\gamma'+\beta) \\ \sin(\gamma'+\beta) \end{pmatrix}
\end{equation}

As we can safely set $t_0=0$ as $t_0$ does only describe a rotation, with \cref{eq:start} inserted in \cref{eq:AtoB} we get the following two equations.
\begin{subequations}
\begin{align}
    r + \frac{\wline}{2} & = r\cos t_1 + \tau \cos(\gamma'+\beta) \label{eq:system:a}\\
    0 & = r \sin t_1 + \tau  \sin(\gamma'+\beta) \label{eq:system:b}
    \intertext{We can insert \cref{eq:system:b} in \cref{eq:system:a} eliminating $\tau$ and after dividing through $r$ we get}
    1 + \frac{\wline}{2r} & = \cos t_1 - \sin t_1 \frac{\cos(\gamma'+\beta)}{\sin(\gamma'+\beta)} \\
    1 + \frac{\wline}{2r} & = \cos t_1 - \sin t_1 \cot\left(\frac{t_1-t_2}{2} - \frac{\pi}{2} + \beta\right) \label{eq:notyetfinal}
\end{align}
\end{subequations}

What follows now are some trigonometric formulae.
\begin{subequations}
\begin{align}
    \cos x & = \sqrt{1-\sin^2x} \label{eq:sincos}\\
    \sin\left(x+\frac{\pi}{2}\right) & = \cos x \\ \cos\left(x+\frac{\pi}{2}\right) & = - \sin x \\
    \cot\left(x+\frac{\pi}{2}\right) = \frac{\cos\left(x+\frac{\pi}{2}\right)}{\sin\left(x+\frac{\pi}{2}\right)} &
    = - \frac{\sin x}{\cos x} = - \tan x \\
    \intertext{with $x=x'-\pi$ we get}
    \begin{split}
    \cot\left(x'-\frac{\pi}{2}\right) & = - \tan(x'-\pi) \\ & = \tan x' \label{eq:cottan} \end{split}\\ \intertext{as well as}
    \tan (x + y) & = \frac{ \tan x + \tan y }{ 1 - \tan x \cdot \tan y } \label{eq:tantan}
\end{align}
\end{subequations}

With \cref{eq:cottan} substituted in \cref{eq:notyetfinal} we can say that
\begin{equation}
    1 + \frac{\wline}{2r}  = \cos t_1 - \sin t_1 \tan\left(\frac{t_1-t_2}{2} + \beta\right) \label{eq:stillnotfinal}
\end{equation}
\Cref{eq:stillnotfinal} can further ``simplified'' with \cref{eq:aux:t2} to
\begin{equation}
    1 + \frac{\wline}{2r} = \cos t_1 - \sin t_1 \tan \left[
        t_1 + \beta - \arcsin \left(\frac{\larrow-\iarrow}{2r} \right)\right] \label{eq:halfgoal}
\end{equation}

At this point, the whole \cref{eq:halfgoal} does only have one unknown variable: $t_1$.

\section{Approximation}
\Cref{eq:halfgoal} with \cref{eq:tantan}:
\begin{equation}
    1 + \frac{\wline}{2r} = \cos t_1 - \sin t_1 \frac{\tan t_1 + \tan\left(\beta - \arcsin \left(\frac{\larrow-\iarrow}{2r} \right)\right)}{1-\tan t_1 \tan \left(\beta - \arcsin \left(\frac{\larrow-\iarrow}{2r} \right)\right)} \label{eq:notquiteyet}
\end{equation}

In \cref{eq:notquiteyet} we do the following substitutions.
Following \cref{eq:system:b} we can be satisfied with $\sin t_1$:
\begin{subequations}\label{eq:subs}
\begin{align}
    \sin t_1 & = t' \\
    \shortintertext{For small angles:}
    \tan t_1 & \approx \sin t_1 = t' \\
    \cos t_1 & = 1 \\
    \cos t_1 & = \sqrt{\smash[b]{1-\sin^2t_1}} = 1 \quad \text{(See \cref{eq:sincos}.)} \\
    \tan \left(\beta - \arcsin \left(\frac{\larrow-\iarrow}{2r} \right)\right) & = u 
    \pgfmathparse{tan(\angBeta-asin((\the\arLength-\the\arInset)/(2*\the\dimRadius))}
    = \pgfmathresult\pt
\end{align}
\end{subequations}

With the \cref{eq:subs} we get for \cref{eq:notquiteyet}:
\begin{subequations}
\begin{align}
    1 + \frac{\wline}{2r} & = 1 - t' \frac{t'+u}{1-ut'} \\
    \frac{\wline}{2r} - \frac{u\wline}{2r} t' & = - {t'}^2 - u t' \\
    {t'}^2 + \left(u-\frac{u\wline}{2r}\right)t' + \frac{\wline}{2r} & = 0 \label{eq:quadratic}
\end{align}
\end{subequations}

The solution of \cref{eq:quadratic} is
\begin{align}
    t'_{1,2} = \frac{u\wline}{4r} - \frac{u}{2} \pm \sqrt{\frac{u^2\wline^2}{16r^2}-\frac{u^2\wline}{4r}+\frac{u^2}{4}-\frac{w}{2r}}
\end{align}
\end{document}

Conclusion

Well, I messed up. Even a numerical solution of the (thought-to-be) precise equation is not possible, which must mean that somewhere along the path to that equation I have must encountered an error.

3
  • Temporarily I accept this answer even though I have not checked it yet (as I am too busy to do something). Your effort looks well-considered! Thank you! Dec 25, 2012 at 7:06
  • @GarbageCollector Thanks, but I have gotten us nowhere. ;) (And going over it now I see already that I have missed an factor of 1/2.) I am sure that some people either see my errors or better yet come up with an easier solution. Dec 25, 2012 at 7:10
  • 1
    @Qrrbrbirlbel in (3a): l_{arrow}-i_{arrow}=2r*sin[(t_1+t_2)/2], however it seems to me that eq. 10 is correct. With your values, I get t_1 ≈ 2.241676671, hence arcsepB ≈ 11.14.
    – Luigi
    Dec 27, 2012 at 16:24
15
+50

draw the complete arc first and then the arrow or use a simple \psline with polar coordinates:

\documentclass[pstricks,border=12pt]{standalone}
\SpecialCoor
\psset{linewidth=5\pslinewidth}
\begin{document}

\begin{pspicture}(3,3)
   \psarc(0,0){3}{0}{90}
   \psline[arrows=->,arrowscale=2,linestyle=none](3;46)(3.0005;46.1)
\end{pspicture}

\begin{pspicture}(3,3)
\psarc(0,0){3}{0}{90}
\psarc[arrowscale=2]{->}(0,0){3}{0}{45}
\end{pspicture}

\end{document}

enter image description here

1
  • Unless there is such a formula, I will happily accept this answer. Oct 28, 2012 at 13:24
2

Herbert's answer is probably the most simple and should be preferred. As the problem is interesting from a mathematical point of view, I just wanted to sketch some mathematical solution, as it might be interesting for someone.

Let's first assume, that the radius of your arc (circle) is very large compared to its line width (infinitely large, otherwise see later). Then, the arrow has to be shifted "to the front". You can find out how large the shift is by using the intercept theorem. In your case it's scaling the arrow length by the width ratio, i.e.,

shift = arrowLength * lineWidth / arrowWidth.

The remaining question is: How much is a shift forward in angle? This obviously depends on the radius. Using a similar idea as above leads to

shift / (2 * pi * radius) = shiftAngle / 360°.

So all in all you get

shiftAngle = (arrowLength * lineWidth * 360°) / (2 * pi * radius * arrowWidth).

This is all fine, but what if the arc is not very large compared to the line width? One additional problem (there might be more, depending on the implementation in pstricks) is, that the line does not have one radius due to its linewidth, but at least a center radius, an inner radius and an outer radius. To be on the save side, you could always shift by the inner radius, as this will lead to the largest shiftAngle.

3
  • the radius also depends to the dimen setting: inner, outer, or middle
    – user2478
    Nov 1, 2012 at 8:53
  • Can you apply your calculation to a complete code? Nov 3, 2012 at 20:02
  • Sorry, but I lack the pstricks knowledge to do something useful here, so I better skip it before I mislead someone. As written, the other answers are the way to go, I just wanted to give a hint for the mathematics. Dec 19, 2012 at 20:35

You must log in to answer this question.

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