7

I'd like to draw an optics-related figure, for which I need to draw several beams with varying opening angles, which will need to be labeled.

What I've come up at the moment (boiled down to a minimal example) is below:

\documentclass{article}

\usepackage{tikz}
    \usetikzlibrary{intersections}
\usepackage[active,tightpage]{preview}

\begin{document}
\centering
\begin{preview}
\begin{tikzpicture}
    \coordinate (origin) at (0,0);
    \coordinate (screen-top) at (5,2);
    \coordinate (screen-bottom) at (5,-2);
    \draw [dashed,name path=beam] (origin) -- (screen-top) -- (screen-bottom) -- cycle;
    \draw [green,name path=circle] (0,0) circle (1);
    \path [name intersections={of=beam and circle,name=arc}];
    \draw [bend left] (arc-1) to node [midway,right] { \(\alpha\)} (arc-2) ;
\end{tikzpicture}
\end{preview}
\end{document}

Now I have a problem with this code. I can't seem to be able to automatically figure out the correct bending angle of the path between the intersections (the creen circle and the beam), so the bend is not 'nice', as seen in the figure below.

I know that I can manually set the bending angle with [bend left=19] instead of [bend left], but doing this manually for all drawings seems like not doing it the TikZ-way.

Problem

Does anyone have a tip for automatically calculating the bending angle for the path so it automatically matches a circle going through that point? Automatically means for different beam angles and 'screen' sizes and positions (which can be set in the code...)

3 Answers 3

3

Here are two solutions. The first clips a circle. The second actually computes the required angle, then draws the arc.

The code is

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{intersections}
\usetikzlibrary{calc}

\begin{document}

%option 1
\begin{tikzpicture}

\coordinate (origin) at (0,0);
\coordinate (screen-top) at (5,2);
\coordinate (screen-bottom) at (5,-2);

\draw [dashed,name path=beam] (origin) -- (screen-top) -- (screen-bottom) -- cycle;
\draw [green,name path=circle] (0,0) circle (1);

\clip (origin) -- (screen-top) -- (screen-bottom) -- cycle;
\draw (origin) circle[radius=1];
\node[right] at (1,0) {$\alpha$};

\end{tikzpicture}

%option 2
\begin{tikzpicture}
\pgfmathsetmacro{\radius}{1}

\coordinate (origin) at (0,0);
\coordinate (screen-top) at (5,2);
\coordinate (screen-bottom) at (5,-2);

\draw [dashed,name path=beam] (origin) -- (screen-top) -- (screen-bottom) -- cycle;
\draw [green,name path=circle] (0,0) circle (\radius);

\draw let
        \p{a} = ($(screen-top) - (origin)$),
        \p{b} = ($(screen-bottom) - (origin)$),
        \n{inner product} = {(\x{a}/1cm)*(\x{b}/1cm) + (\y{a}/1cm)*(\y{b}/1cm)},
        \n{la} = {veclen(\x{a}/1cm,\y{a}/1cm)},
        \n{lb} = {veclen(\x{b}/1cm,\y{b}/1cm)},
        \n{cosine} = {\n{inner product}/(\n{la}*\n{lb})},
        \n{half-angle} = {0.5*acos(\n{cosine})}
        in 
        (arc-2) arc[start angle=-\n{half-angle},end angle=\n{half-angle},radius = \radius] node[right] at ($(origin) + (\radius,0)$){$\alpha$};



\end{tikzpicture}


\end{document} 

Comment for Habi: You may replace the code defining the arc by the following line, in which the arc starts at arc-1:

(arc-1) arc[start angle=\n{half-angle},end angle=-\n{half-angle},radius = \radius] node[right] at ($(origin) + (\radius,0)$){$\alpha$};
2
  • Using a clipped circle as 'workaround' is quite elegant. I'll use this, also because the second option doesn't compile for me (with '! Package pgf Error: No shape named arc-2 is known.' as error).
    – Habi
    Commented Jan 19, 2012 at 17:03
  • @Habi: see comment at bottom of my post.
    – Frédéric
    Commented Jan 19, 2012 at 18:26
6

With tkz-euclide, you need only one line.

\documentclass{scrartcl}
\usepackage{tkz-euclide} 
\usetkzobj{all} 
\begin{document}

\begin{tikzpicture}
  \tkzDefPoint(1,1){O}  \tkzDefPoint(3,-1){A}  \tkzDefPoint(4,2){B}
  \tkzDrawArc[R with nodes, color=blue](O,2cm)(A,B)
  \tkzDrawArc[R with nodes, color=red](O,2cm)(B,A)
  \tkzDrawLines[add = 0 and .5](O,A O,B)
  \tkzDrawPoints(O,A,B)
  \tkzLabelPoints[below](O,A,B)
\end{tikzpicture} 

\end{document}

enter image description here

5

This is not a direct answer to your question, however, since you know where origin of the rays is and to which points they lead, here is another approach:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.markings}
\tikzset{arcnode/.style={
            decoration={
                        markings, raise = 2mm,  
                        mark=at position 0.5 with { 
                                    \node[inner sep=0] {#1};
                        }
            },
            postaction={decorate}
      }
}

\newcommand*\marktheangle[5]{
            \draw[thick,arcnode={#5}] let \p2=($(#2)-(#1)$),%
                        \p3=($(#3)-(#1)$),%
                        \n2 = {atan2(\x2,\y2)},%
                        \n3 = {atan2(\x3,\y3)}%
                        in ($(\n2:#4)+(#1)$) arc (\n2:\n3:#4);
            }

\begin{document}
\begin{tikzpicture}
\draw[style=help lines] (-0.5,-0.5) grid[step=1cm] (4.5,2.5);
\node[draw,red,circle,minimum width=2cm] (O1) at (1,1) {}; 
\node[draw,red,circle,minimum width=1cm] (O2) at (3.5,1.5) {}; 
% Define 4 points "out there"
\node (a) at (1.5,-0.8) {$a$};
\node (b) at (-5mm,-5mm)  {$b$};
\coordinate (c) at (4.5,1);
\coordinate (d) at (3,2.5);

\draw[loosely dashed,blue] (O1.base) -- (a) (O1.base) -- (b); % Draw the lines
\draw[loosely dashed,green] (O2.base) -- (c) (O2.base) -- (d); %Draw the lines

% the code for the arc labeling
\marktheangle{O1}{a}{b}{1cm}{$\alpha$}
\marktheangle{O2}{d}{c}{5mm}{$\beta$} % Mind the order for label positioning.
\end{tikzpicture}
\end{document}

enter image description here

Now, in his answer to this question, Cjorssen mentions that in the new version, one can directly place a node on an arc. So the whole marking code might be obsolete quite soon or immediately if you wish to use the CVS version. One can further embed these into one nice tikzset definition with better key handling.

1
  • A clever solution, but quite lenghty in terms of code. The other answer to my question suggested simply using a clipped circle, which is what I will go for. Thanks for the work though!
    – Habi
    Commented Jan 19, 2012 at 17:04

You must log in to answer this question.

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