[Tex/LaTex] Draw arrows ending at half circle

tikz-pgf

I am trying to draw a fairly simple scene with tikz.
enter image description here

The issue i have is with defining the end points on half circle. I tried to implement an algorithm
for intersection detection, pseudocode can be found at Circle-Line intersection. However it does not work as it should. In addition, it does not compile if i use the \ifthenelse clause.

Any suggestions on how to get this to work?

\documentclass[11pt]{article}
\usepackage{tikz}
\usepackage{ifthen}
\usepackage{graphics, tkz-berge, tkz-graph}
%%%<
\usepackage{verbatim}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{5pt}%
%%%>

\tikzset{isometricXYZ/.style={x={(-0.866cm,-0.5cm)}, y={(0.866cm,-0.5cm)}, z={(0cm,1cm)}}}

%% document-wide tikz options and styles
\begin{document}
\begin{tikzpicture} [scale=4, line join=round,
        opacity=.75, fill opacity=.35, text opacity=1.0,%
        >=latex,
        inner sep=0pt,%
        outer sep=2pt,%
    ]
% First argument is a ray angle, second argument is an offset along x-axis.
    \newcommand{\ray}[2]{
      \def\r{1} % sphere radius
      \def\l{2} % line length
      \def\xc{#2} % offset

      % Sphere center
      \def\Cx{0}
      \def\Cy{0}

      % Ray start
      \def\Ex{(\xc + (\l*cos(#1)))}
      \def\Ey{(\l*sin(#1))}

      % Ray end
      \def\Lx{\xc}
      \def\Ly{0}

      % Vector from ray start to end
      \def\dx{(\Lx -\Ex)}
      \def\dy{(\Ly -\Ey)}

      % Vector from ray start sphere center
      \def\fx{(\Ex - \Cx)}
      \def\fy{(\Ey - \Cy)}

      % solve eq
      \def\a{(\dx * \dx + \dy * \dy)}
      \def\b{(2 * \fx * \dx + \fy * \dy)}
      \def\c{(\fx * \fx + \fy * \fy - \r * \r)}
      \def\discriminant{(\b*\b - 4*\a*\c)}
      \ifthenelse{{\discriminant} < 0}
      {
          \def\endc{(\xc, 0)}
      }
      {
          \def\sqdiscriminant{sqrt(\discriminant)}
          \def\t{(-\b +\sqdiscriminant)/(2*\a)}
          \def\endc{({\Ex + \t*\dx}, {\Ey + \t*\dy})}
      }

      \def\startc{({\Ex}, {\Ey})}
      \draw [->] \startc -- \endc;
    }

    \draw[fill=gray, fill opacity=0.2] (1, 0) arc (0:180:1);

    \draw [dotted] (0, 0) -- ({cos(30)}, {sin(30)}) node[above right] {$\alpha_1$};
    \draw [dotted] (0, 0) -- ({cos(150)}, {sin(150)}) node[above left] {$\alpha_2$};
    \draw [dotted] (0, 0) -- (0, 1.1);

    \node[below right] (halfpi) at (1, 0) {$\frac{\pi}{2}$};
    \node[below left] (minushalfpi) at (-1, 0) {$-\frac{\pi}{2}$};

    \foreach \x in {2}
    {
      \ray{55}{\x}
    };

\end{tikzpicture}
\end{document}

I tested both solutions below, but in both cases i get some intersections picked up incorrectly. I guess that is because i take the first intersection in all cases, which is unfortunately not always the right one. Is there a way to always choose the closest, not the first, intersection? enter image description here

p.p.s 🙂
nvm. I fixed it by reversing the path direction.

Best Answer

You can simply use the intersections library to avoid calculating the intersections of the rays and the circle manually. It even works for moderately complex paths like the combined half-circle-and-line path.

In order to get the intersection closest to the "light source", you can start the ray at the light source and then use the option sort by=ray. This way, (interection-1) is always the one closest to the source.

And yes, TikZ does all the calculation and sorting using TeX. Witchcraft!

Many intersections

\documentclass[tikz,margin=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections}

\begin{document}
\begin{tikzpicture} [scale=4, line join=round, >=latex]
    % Name this path for intersections
    \draw[fill=gray, fill opacity=0.2, name path=outline]
        (-2,0) -- (-1,0) arc (180:0:1)-- (2,0) ;

    \draw [dotted] (0, 0) -- ({cos(30)}, {sin(30)}) node[above right] {$\alpha_1$};
    \draw [dotted] (0, 0) -- ({cos(150)}, {sin(150)}) node[above left] {$\alpha_2$};
    \draw [dotted] (0, 0) -- (0, 1.1);
    \node[below right] (halfpi) at (1, 0) {$\frac{\pi}{2}$};
    \node[below left] (minushalfpi) at (-1, 0) {$-\frac{\pi}{2}$};

    % Properties of the "light source"
    \def\angle{45}
    \def\width{2.8cm}

     % Draw the light source:
    \draw[very thick] (\angle:2.5cm) coordinate(light)
        ++(\angle+90:0.5*\width) -- +(\angle-90:\width);
    % Draw a number of rays:
    \foreach \x in {-8,...,8} {
        % Place a path from light source through circle and name it:
        \path[name path=ray,overlay] (light) ++(\angle+90:\x*\width/17)
            coordinate(start) -- +(180+\angle:5cm);
        % Draw the arrow from light source to first intersection:
        \draw[->, name intersections={of=outline and ray, sort by=ray}]
            (start) -- (intersection-1);
    }
\end{tikzpicture}
\end{document}