# TikZ - drawing multiple lines from the origin to the edge of an *arc*

I am trying to produce a diagram showing wavefronts/rays spherically diverging from some origin, and being paraxially rectified when contacting a lens with some controlled radius. What I want is something like this: The sketch is a really rough one — I'm just trying to convey the idea, and not yet sure exactly the best way to do this... so I'm obviously open to suggestions!

I have thoroughly read and experimented with the answers provided here which draws a line from a circle's origin to its perimeter, but I'm unsure how to adapt it to my needs.

The closest I've come to a solution is based on this method of marking the centre of an arc and this method of marking a path with a node which I can use to mark various points (literally just punctuation marks) along a convex arc.

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{shapes.geometric,positioning}
\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}[
% parametrise an arc
arcnode/.style 2 args={
decoration={
raise=0pt,
markings,
mark=at position #1 with {
\node[inner sep=0] {#2};
}
},
postaction={decorate}
}
]

\foreach \frac in {0,0.1,...,1}
\draw[-, black, arcnode={\frac}{.}] [] (4cm,0) arc (-30:-150:2cm);

\end{tikzpicture}

\end{document}


Which draws the arc itself several times and is obviously not even close to working as I'd like it to. This is my first time using tikZ for anything even vaguely complicated, and I'm pretty stumped :(

I'm stuck and running out of time for a submission, so I would really appreciate some help!

EDIT:

After some thought and after looking through Qrrbrbirlbel's suggested TikZ code, I have come up with the following closer approximation to what I'd ultimately like to produce:

\documentclass[tikz]{standalone}
\usetikzlibrary{intersections,through}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[dot/.style={circle, fill, draw, inner sep=+0pt, minimum size=+3pt}]

\pgfmathsetmacro\nRays{4}
\pgfmathsetmacro\nAngle{33.367}

\pgfmathsetmacro\nAngleMin{90-\nAngle}
\pgfmathsetmacro\nAngleMax{90+\nAngle}
\pgfmathsetmacro\nAnglePP{floor((\nAngleMax-\nAngleMin)/(\nRays-1))}
\pgfmathsetmacro\nAngleInc{\nAngleMin+\nAnglePP}

\pgfmathsetmacro\lensH{1}
\pgfmathsetmacro\lensAbove{2.5}

\pgfmathsetmacro\toptobottom{5}

\draw (left:\lensRad) to[out=90,  in=90,  looseness=.1]  ++(right:\lensDia)
-- ++(down:\lensH)                                      coordinate (s-1)
to[out=-90, in=-90, looseness=.5]  ++(left:\lensDia) coordinate (s-2)
-- cycle [name path=shield];

\path (down:\toptobottom) coordinate (M) ++ (\nAngleMin:1) coordinate (M-1) ++ (\nAngleMin:.5) coordinate (M-2)
(up:\lensAbove)   coordinate (S3);

% \node[circle through=(M-1), draw, outer sep=+.5\pgflinewidth] (M1) at (M) {};
\node[dot, draw, outer sep=+.5\pgflinewidth] (M1) at (M) {};

\draw[dashed] (M-2) arc [radius=1.5, start angle=\nAngleMin, end angle=\nAngleMax]
(s-1) -- (s-2)

\draw[dashed] (s-2) arc [radius=1.5, start angle=-\nAngleMin, end angle=-\nAngleMax];

\path[name path=rays] \foreach \a[count=\i] in {\nAngleMin, \nAngleInc, ..., \nAngleMax} {(M) -- node[dot, pos=.375] (d-\i) {} ++ (\a:4)};
\path[name intersections={of=rays and shield, name=down}, overlay, name path=up-rays]

\foreach \i in {1,...,\nRays} {([shift=(up:1)] down-\i) -- ++(up:3)};
\path[name intersections={of=up-rays and shield, name=up}] \foreach \i in {1,...,\nRays} {
node[dot] at (intersection of s-1--s-2 and down-\i--up-\i) {}
node[dot] (up'-\i) at ([xscale=.2] up-\i|-S3) {}                                };

\foreach \i in {1, ..., \nRays} \draw (M1) -- (down-\i) -- (up-\i) -- (up'-\i);

%Now draw some coordinate systems and annotations:

% Coordinates system  1
\draw[<->,line width=1pt] (1,0-\toptobottom) -|(0,1-\toptobottom);
% \draw(0,-0.15)node[below]{$y$};
\draw(-0.35,-0.25-\toptobottom)node[above]{$y_1$};
\draw(1.25,-0.25-\toptobottom) node[above]{$z_1$};
\draw(-0.35,0.8-\toptobottom) node[above]{$x_1$};

% $y$ axis
\filldraw[fill=white,line width=1pt](0,0-\toptobottom)circle(.12cm);

\pgfmathsetmacro\shift{4.5}

% Coordinates system 2
\draw[<->,line width=1pt] (1,0+\shift) -|(0,-1+\shift);
% \draw(0,-0.15)node[below]{$y$};
\draw(-0.35,-0.25+\shift)node[above]{$y_2$};
\draw(1.25,-0.25+\shift) node[above]{$z_2$};
\draw(-0.35,-1.25+\shift) node[above]{$x_2$};

% $y$ axis
\filldraw[fill=white,line width=1pt](0,0+\shift)circle(.12cm);

% \fill[gray!10,rounded corners] (-3,-2) rectangle (4,0);
% \fill[gray!10] (-3,-2.5) rectangle (4,0);

% Interface pointer 1
\draw[-latex,thick](1.2,1.5-\toptobottom)node[right]{$W_{1}$}
to[out=180,in=90] (1,1-\toptobottom);

% Interface pointer 2
\draw[-latex,thick](1.2,-3.5+\shift)node[right]{$W_{2}$}
to[out=180,in=90] (1,-4.0+\shift);

% Interface pointer 3
\draw[-latex,thick](1.2,-1.5+\shift)node[right]{$W_{3}$}
to[out=180,in=90] (1,-2.0+\shift);

\end{tikzpicture}

\end{document}


This produces the following figure (I'm currently trying to figure out out to "mirror" the arc at the bottom of the figure onto the top area, after the lens): Which is much closer to what I ultimately want but not quite there yet. It seems like Qrrbrbirlbel's solution should be "easily" (for some folk!) adjusted to get my ideal figure.

Obviously I've revised the features I'm looking for slightly — a better guide might have been the following: Which I can then annotate to indicate the various coordinate systems.

EDIT:

For additional clarification, I have annotated another sketch of what I'm trying to achieve: • I'm not sure if I understand your question properly so correct me if I'm wrong. You want to generate the points that you have labelled with S1? – Pouya Nov 13 '13 at 9:55
• @Pouya Sorry if I haven't been clear - I want to generate the whole thing. So that is to say I want to generate lines coming from the origin, making contact with the convex lens, changing direction and heading paraxially up, and then changing direction again to focus toward a point above the lens. – chroma Nov 13 '13 at 13:19
• What are the properties of the small coordinate systems. One of the axis clearly goes along the line. But what about the other axis? Is it orthogonal to the first one?. It looks like the circles aren’t centered at the origin and the target of the line. – Qrrbrbirlbel Nov 18 '13 at 12:17
• Those are meant to be unit vectors in altered spherical coordinates, so they ought to be orthogonal. You're quite right, the sketch was a little vague and the non-radial axes almost look tangential. Ooops! – chroma Nov 18 '13 at 21:22
• To be clear: the non-radial axes should be orthogonal to the radial axes and tangential to the arcs, since these are projections of reference spheres centred on each origin. The dots are meant to indicate the out-of-plane axes and so definitely should lie precisely on the radial line. I think this is just a matter of building from the 'leftmost' node for each side of the lens, but I'm unsure how to pull out tangents and such. – chroma Nov 18 '13 at 21:44 An Asymptote suggestion. You might need to adjust the lens outline.

//
// lens.asy :
//
size(200);
import graph;
import math;
import fontsize;

texpreamble("\usepackage{lmodern}");

defaultpen(fontsize(9pt));

pen borderPen=deepblue+1bp;
pen linePen=gray(0.3)+0.4bp;
pen dashPen=linePen+linetype(new real[] {4,4});
pen arcPen=red+1bp;

pair[] p={(0,0),(159,22),(186,34),
(199,41),(215,68),(216,160),(211,166),
(196,172),(64,185),(0,188),
};

transform t=scale(-1.05,1);

guide glens=p
..p..p..p
..p{dir(90)}
..{dir(90)}p
..p
..p
..p
..t*p
..t*p
..t*p{dir(-90)}
..{dir(-90)}t*p
..t*p
..t*p
..t*p
..cycle;

real r=65;
pair c=(0,-130);

draw(glens,borderPen);
draw(Circle(c,r),borderPen);

real R=1.618r;
real phi=24.6;
draw(Arc(c,R,90-2phi,90+2phi),dashPen);

pair[] S0=new pair;
S0=c+(0,r);
S0=rotate(-2phi,c)*S0;
S0=rotate( -phi,c)*S0;
S0=rotate(  phi,c)*S0;
S0=rotate( 2phi,c)*S0;

pair[] S1=new pair;
S1=c+(0,R);
S1=rotate(-2phi,c)*S1;
S1=rotate(-phi,c)*S1;
S1=rotate(phi,c)*S1;
S1=rotate(2phi,c)*S1;

guide top=subpath(glens,5,11);
guide bottom=subpath(glens,12,16)&subpath(glens,0,4);

guide botRay=c--(c+arclength(c--p)*N);

pair[] botPoints;
for(int i=-2;i<=2;++i){
botPoints.push(intersectionpoint(rotate(i*phi,c)*botRay,bottom));
draw(S0[i+2]--botPoints[i+2],linePen);
}
pair[] S3={(122,290),(49,290),(0,290),(-55,290),(-161,290)};

pair[] topPoints;
pair[] S2;
guide midRay;
guide midSect=p--t*p;
real th=2arclength(p--p);
for(int i=0;i<botPoints.length;++i){
midRay=botPoints[i]--(botPoints[i]+(0,th));
topPoints.push(intersectionpoint(midRay,top));
S2.push(intersectionpoint(midRay,midSect));
draw(topPoints[i]--S3[i],linePen);
draw(botPoints[i]--topPoints[i],linePen);
}

draw(midSect,dashPen);
draw(S3--S3,dashPen);

dot(S1,UnFill);
dot(S2,UnFill);
dot(S3,UnFill);

guide arcArr1=(162,-30)..(107,-5)..(58,-40);
guide arcArr2=(257,70)..(221,96)..(181,69);
guide arcArr3=(183,296)..(144,321)..(104,294);

label("$S_1$",point(arcArr1,0),SW);
label("$S_2$",point(arcArr2,0),SW);
label("$S_3$",point(arcArr3,0),SW);


To get a standalone lens.pdf, run asy -f pdf lens.asy.

• Thank you very much for taking the time to offer up an alternative. I'm having quite a bit of trouble getting my head around TikZ, but have half a dozen (simple) figures with a nicely consistent look to them so I would prefer to stick with one toolset for now. Thanks again :) – chroma Nov 18 '13 at 5:22
• @lams: It is always nice to have options. Btw, you can convert this lens.asy code to TikZ via SVG format by commands asy -f svg lens.asy; svg2tikz lens.svg > lens-tikz.tex. The converter is not perfect, it produces too verbose output and I can't get the labels with it, but it generates a pure TikZ code. – g.kov Nov 18 '13 at 19:29
• I'm not familiar with Asymptote, but I may try it out next time I run into a TikZ problem because you're right — it is always nice to have options. Thanks again :) – chroma Nov 18 '13 at 23:51

Two approaches with TikZ.

The first one uses the intersections library and fixed angles for the lower rays. The factor .8 shows up twice: In the xscale of the most-upper dots (in relation to the dots on the upper part of the “shield”) and in the drawing of the upper dashed line.

The second approach uses nodes along the to parts of the “shield”. The rest is pretty much the same. The dashed arc at the bottom of the diagram states an extra task that I have left out of the answer. This can be either solved again with the intersections library or the calc library (which will be needed for the arc either way if you won’t use something along the lines of Tikz: joining points on a circle).

## Code 1

\documentclass[tikz]{standalone}
\usetikzlibrary{intersections,through}
\begin{document}
\begin{tikzpicture}[dot/.style={circle, fill, draw, inner sep=+0pt, minimum size=+3pt}]
\draw (left:3.5) to[out=90,  in=90,  looseness=.1]  ++(right:7)
-- ++(down:2)                                      coordinate (s-1)
to[out=-90, in=-90, looseness=.5]  ++(left:7) coordinate (s-2)
-- cycle [name path=shield];

\path (down:5) coordinate (M) ++ (40:1) coordinate (M-1) ++ (40:.5) coordinate (M-2)
(up:2)   coordinate (S3);

\node[circle through=(M-1), draw, outer sep=+.5\pgflinewidth] (M1) at (M) {};

\draw[dashed] (M-2) arc [radius=1.5, start angle=40, end angle=140]
(s-1) -- (s-2)
([shift=(left:3.5*.8)] S3) -- ([shift=(right:3.5*.8)] S3);

\path[name path=rays] \foreach \a[count=\i] in {40, 65, ..., 140}
{(M) -- node[dot, pos=.375] (d-\i) {} ++ (\a:4)};
\path[name intersections={of=rays and shield, name=down}, overlay, name path=up-rays]
\foreach \i in {1,...,5} {([shift=(up:1)] down-\i) -- ++(up:3)};
\path[name intersections={of=up-rays and shield, name=up}] \foreach \i in {1,...,5} {
node[dot] at (intersection of s-1--s-2 and down-\i--up-\i) {}
node[dot] (up'-\i) at ([xscale=.8] up-\i|-S3) {}                                };

\foreach \i in {1, ..., 5} \draw (M1) -- (down-\i) -- (up-\i) -- (up'-\i);
\end{tikzpicture}
\end{document}


## Code 2

\documentclass[tikz]{standalone}
\usetikzlibrary{through}
\makeatletter
\pgfkeys{/handlers/.pgfmath/.code=%
\pgfmathparse{#1}\expandafter\pgfkeys@exp@call\expandafter{\pgfmathresult}}
\tikzset{edge node/.code=% CVS
{\expandafter\def\expandafter\tikz@tonodes\expandafter{\tikz@tonodes#1}}}
\makeatother
\tikzset{
en name/.initial=up,
en/.style ={
edge node={coordinate[pos/.pgfmath=#1/6]     (\pgfkeysvalueof{/tikz/en name}-#1)}},
en'/.style={
edge node={coordinate[pos/.pgfmath=(6-#1)/6] (\pgfkeysvalueof{/tikz/en name}-#1)}}}
\begin{document}
\begin{tikzpicture}[dot/.style={circle, fill, draw, inner sep=+0pt, minimum size=+3pt}]
\draw (left:3.5) to[out=90,  in=90,  looseness=.1, en/.list={1,...,5}] ++(right:7)
-- ++(down:2) coordinate (s-1)
to[out=-90, in=-90, looseness=.5, en name=down, en'/.list={1,...,5}] ++(left:7)
coordinate (s-2) -- cycle;
\path (down:5) coordinate (M)
++ (0:1)  coordinate (M-1)
++ (0:.5) coordinate (M-2)
(up:2) coordinate (S3);
\path \foreach \i in {1,...,5} {
node[dot] at (intersection of s-1--s-2 and down-\i--up-\i) {}
node[dot] (up'-\i) at ([xscale=.8] up-\i|-S3) {}};

\node[circle through=(M-1), draw, outer sep=+.5\pgflinewidth] (M1) at (M) {};
%\node[circle through=(M-2), overlay] (M2) at (M) {};
\foreach \i in {1, ..., 5} \draw (M1) -- (down-\i) -- (up-\i) -- (up'-\i);
\draw[dashed] (M-2) arc [radius=1.5, start angle=0, end angle=180]
(s-1) -- (s-2)
([shift=(left:3.5*.8)] S3) -- ([shift=(right:3.5*.8)] S3);
\end{tikzpicture}
\end{document}


## Outputs  • Thanks so much for two excellent starting points! The first block gave a closer approximation to what I was initially looking for, so I started with that. I have made an ammendment to my question to include some modifications to your first code block — hopefully you can help to finally set me straight! – chroma Nov 18 '13 at 5:24