Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Is there a library (or something similar) available for optics including e.g. convex and concave lenses? I fount this but it seems that this is not available as an official library …

share|improve this question
    
This appears to has been sitting there for a while: launchpad.net/optikz. Good name by the way. –  Roelof Spijker Nov 2 '11 at 15:12
1  
Now this would be a real nice feature request for a future version of TikZ! –  Count Zero Nov 2 '11 at 16:32
    
@CountZero: So there is none yet? If you post this as an answer I’ll accept it … Is there an official way to ask for a new feature? –  Tobi Nov 2 '11 at 17:17
    
    
there was a similar request for chemical lab equipment library <tex.stackexchange.com/questions/3878/…; which also would be a handy feature... –  Leeser Nov 3 '11 at 15:31
add comment

4 Answers

AFAIK, such a library does not exist yet.

As you mentioned, I started something a while ago, but I did not have, at that time, enough tikz/pgf knowledge to circumvent some difficulties I found.

The idea is to use the shapes/nodes mechanism to define anchors (such as image focus, center, etc.) and then use them to draw useful light rays.

Here is an example of the syntax I would have liked to have (hope it is clear enough).

\begin{tikzpicture}
  \node[converging lens,anchor=center,image focal length=2.5cm] (L1) at (0,0)
    {$\mathcal{L}_1$};
  \node[diverging lens,anchor=center,image focal length=-1.5cm] (L2)
    at ($(L1.center)!5cm!(L1.optical axis forward)$) {$\mathcal{L}_2$};

  \node[object for lens=L1,height=1.5cm,anchor=bottom] (Object1) at
    ($(L1.center)!-2*\pgfkeysvalueof{pgf/optics/L1/focal
      length}!(L1.optical axis forward)$) {};
  \draw[LR>] (Object1.top) -- ($(L1.top)!(Object1.top)!(L1.bottom)$)
    -- (Object1.image top by L1);
  \draw[LR>>] (Object1.top) -- (L1.center) -- (Object1.image top by L1);
  \draw[LR>>>] (Object1.top) -- 
    ($(L1.top)!(Object1.image top by L1)!(L1.bottom)$) -- 
    (Object1.image top by L1);

  \node[object for lens=L2,height={TO BE COMPUTED},anchor=bottom] (Object2) at
    (Object1.image top by L1) {};
\end{tikzpicture}

One of the not-so-easy part is to have anchor names depending on node names (such as in the above example Object1.image top by L1). It should also be possible to know if an image is real or virtual and draw the light rays (LR) consistently.

Unfortunately, lack of time led me to a more rustic solution. Here I give a (too?) verbose example of what can be done with tikz (not a library but a kind of template):

\documentclass{standalone}

\usepackage[svgnames]{xcolor}
\usepackage{tikz}

\makeatletter

\usetikzlibrary{arrows,calc,decorations.markings}

\pgfdeclareshape{mark point +}{%
  \anchor{center}{\pgfpointorigin}
  \inheritsavedanchors[from=mark point |]
  \backgroundpath{%
    \pgfsetarrows{-}%
    \pgfsetlinewidth{.8pt}%
    \pgfpathmoveto{\pgfpoint{0}{.8mm}}%
    \pgfpathlineto{\pgfpoint{0}{-.8mm}}%
    \pgfpathmoveto{\pgfpoint{-.8mm}{0}}%
    \pgfpathlineto{\pgfpoint{.8mm}{0}}%
    \pgfusepath{stroke}}}

% Light rays
\tikzset{>=stealth}
\pgfarrowsdeclaredouble{doublestealth}{doublestealth}{stealth}{stealth}
\pgfarrowsdeclaretriple{triplestealth}{triplestealth}{stealth}{stealth}
\pgfarrowsdeclaredouble{quadruplestealth}{quadruplestealth}%
  {doublestealth}{doublestealth}
\pgfarrowsdeclarealias{<<}{>>}{doublestealth}{doublestealth}
\pgfarrowsdeclarealias{<<<}{>>>}{triplestealth}{triplestealth}
\pgfarrowsdeclarealias{<<<<}{>>>>}{quadruplestealth}{quadruplestealth}

\tikzset{%
  LRnoarrow/.style = {thick,gray,nearly opaque},
  LR/.style 2 args = {%
    decoration={markings,mark=at position #2 with {\arrow{#1};}},
    postaction={decorate},
    LRnoarrow},
  VirtualLR/.style = {LRnoarrow,dashed},
  LR>/.style = {LR={>}{#1}},
  LR>/.default = {0.5},
  LR>>/.style = {LR={>>}{#1}},
  LR>>/.default = {0.55},
  LR>>>/.style = {LR={>>>}{#1}},
  LR>>>/.default = {0.6},
  LR>>>>/.style = {LR={>>>>}{#1}},
  LR>>>>/.default = {0.65},
  ConvergingLens/.style = {ultra thick,<->},
  DivergingLens/.style = {ultra thick,>-<},
  OpticalAxis/.style = {very thick,->},
  Object/.style = {very thick,->},
  VirtualObject/.style = {very thick,->,dashed}}

% Annotate an angle
\pgfkeysdef{/tikz/mark angle/start angle}{\tikzset{start angle=#1}}
\pgfkeysdef{/tikz/mark angle/end angle}{\tikzset{end angle=#1}}
\pgfkeysdef{/tikz/mark angle/angle radius}{\tikzset{radius=#1}}
\pgfkeyssetvalue{/tikz/mark angle/label radius}{1cm}
\pgfkeyssetvalue{/tikz/mark angle/label pos}{.5}
\pgfkeyssetvalue{/tikz/mark angle/node options}{}
\pgfkeyssetvalue{/tikz/mark angle/path options}{}
\def\tikzMarkAngle{%
  \pgfutil@ifnextchar[{\tikzMarkAngle@i}{\tikzMarkAngle@i[]}}
\def\tikzMarkAngle@i[#1](#2)(#3)(#4)#5{%
  % #1 optional parameters
  % #2 coordinate of the center
  % #3 coordinate giving the start direction
  % #4 coordinate giving the end direction
  % #5 label
  \bgroup
    \coordinate (xCJtikz@AngleCenter) at (#2);
    \coordinate (xCJtikz@AngleStart) at (#3);
    \coordinate (xCJtikz@AngleEnd) at (#4);
    \pgfmathanglebetweenpoints{%
      \pgfpointanchor{xCJtikz@AngleCenter}{center}}{%
      \pgfpointanchor{xCJtikz@AngleStart}{center}}
    \edef\AngleStart{\pgfmathresult}%
    \pgfmathanglebetweenpoints{%
      \pgfpointanchor{xCJtikz@AngleCenter}{center}}{%
      \pgfpointanchor{xCJtikz@AngleEnd}{center}}
    \edef\AngleEnd{\pgfmathresult}%
    \ifdim\AngleEnd pt<\AngleStart pt\relax
      \pgfmathsetmacro\AngleEnd{\AngleEnd+360}
    \fi
    \pgfkeys{%
      /tikz/mark angle/.cd,
      angle radius=1cm,
      label radius=1.2cm,
      label pos=.5,
      start angle=\AngleStart,
      end angle=\AngleEnd,
      #1}
      \edef\xCJ@temp{%
        \noexpand\draw[\pgfkeysvalueof{/tikz/mark angle/path options}]
        (\noexpand$(xCJtikz@AngleCenter)!\pgfkeysvalueof{/tikz/x
          radius}!(xCJtikz@AngleStart)\noexpand$) arc;
        \noexpand\node[\pgfkeysvalueof{/tikz/mark angle/node options}] at
        (\noexpand$(xCJtikz@AngleCenter)+(\AngleStart+\pgfkeysvalueof{/tikz/mark
          angle/label pos}*\AngleEnd-\pgfkeysvalueof{/tikz/mark
          angle/label pos}*\AngleStart:\pgfkeysvalueof{/tikz/mark angle/label radius})\noexpand$)}%
    \xCJ@temp{#5};%
  \egroup
  \ignorespaces}
\makeatother

\begin{document}

\begin{tikzpicture}
  \coordinate (OpticalAxisLeft) at (0,0);
  \coordinate (OpticalAxisRight) at ($(OpticalAxisLeft)+(13,0)$);
  \draw[OpticalAxis] (OpticalAxisLeft) -- (OpticalAxisRight);
  % 
  \def\LensHeight{5cm}%
  \def\FocalLengthOne{10cm}%
  \def\FocalLengthTwo{-3cm}%
  % Lens 1
  \coordinate[label=below left:$O_1$] (Center1) at
  ($(OpticalAxisLeft)!.1!(OpticalAxisRight)$);
  \coordinate[label=above:$\mathcal{L}_1$] (Top1) at
  ($(Center1)!\LensHeight/2!90:(OpticalAxisRight)$);
  \coordinate (Bottom1) at ($(Center1)!-1!(Top1)$);
  \draw[ConvergingLens] (Bottom1) -- (Top1);
  \coordinate%[label=below:$F_1$] 
  (ObjectFocus1) at
  ($(Center1)!-\FocalLengthOne!(OpticalAxisRight)$) {}; 
  \node[mark point +,label=above left:$F'_1$] (ImageFocus1) at
  ($(Center1)!\FocalLengthOne!(OpticalAxisRight)$) {}; 
  \coordinate (ImageFocalPlane1Top) at
  ($(ImageFocus1)!\LensHeight/2!90:(OpticalAxisRight)$); 
  \coordinate (ImageFocalPlane1Bottom) at
  ($(ImageFocus1)!-1!(ImageFocalPlane1Top)$); 
  % Lens 2
  \pgfmathsetlengthmacro\DistanceOneToTwo{%
    \FocalLengthOne+\FocalLengthTwo}%
  \coordinate[label=below left:$O_2$] (Center2) at
  ($(Center1)!\DistanceOneToTwo!(OpticalAxisRight)$);
  \coordinate[label=above:$\mathcal{L}_2$] (Top2) at
  ($(Center2)!\LensHeight/2!90:(OpticalAxisRight)$);
  \coordinate (Bottom2) at ($(Center2)!-1!(Top2)$);
  \draw[DivergingLens] (Bottom2) -- (Top2);
  \node[mark point +,label=below:$F_2'$] (ImageFocus2) at 
  ($(Center2)!\FocalLengthTwo!(OpticalAxisRight)$) {}; 
  \coordinate[label=below left:$F_2$] (ObjectFocus2) at
  ($(Center2)!-\FocalLengthTwo!(OpticalAxisRight)$) {}; 
  \coordinate (ImageFocalPlane2Top) at
  ($(ImageFocus2)!\LensHeight/2!90:(OpticalAxisRight)$); 
  \coordinate (ImageFocalPlane2Bottom) at
  ($(ImageFocus2)!-1!(ImageFocalPlane2Top)$); 
  % Object at infinity
  \def\ObjectAngle{12}%
  \coordinate (LRBegin) at
  ($(OpticalAxisLeft)+(0,.9*\LensHeight/2)$);
  \coordinate (temp) at ($(LRBegin)+(-\ObjectAngle:1)$);
  \coordinate (IncidencePoint) at (intersection cs: first line =
  {(Top1) -- (Bottom1)}, second line = {(LRBegin) -- (temp)});
  % 
  \coordinate (LRThroughCenter1Begin) at
  ($(Center1)+(LRBegin)-(IncidencePoint)$);
  \coordinate (Image1Top) at (intersection cs: first line =
  {(LRThroughCenter1Begin) -- (Center1)}, second line =
  {(ImageFocalPlane1Top) -- (ImageFocalPlane1Bottom)});
  % 
  \draw[red,dotted,thick] (ImageFocalPlane1Top) --
  (ImageFocalPlane1Bottom);
  \draw[red,dotted,thick] (LRThroughCenter1Begin) --
  ($(Image1Top)!-.1!(LRThroughCenter1Begin)$);
  \node[coordinate,label=below right:$B_1$] at (Image1Top) {};
  \node[coordinate,label=below right:$A_1$] at (ImageFocus1) {};
  \draw[Object,semitransparent] (ImageFocus1) -- (Image1Top);
  % 
  \coordinate (LRIntersectionWithLens2) at
  (intersection cs: first line = {(Top2) -- (Bottom2)}, second line
  = {(IncidencePoint) -- (Image1Top)});
  \coordinate (LRThroughCenter2Begin) at
  ($(Center2)+(IncidencePoint)-(LRIntersectionWithLens2)$); 
  \coordinate[label=above right:$I$]
  (LRThroughCenter2IntersectionWithImageFocalPlane2) at 
  (intersection cs: first line = {(ImageFocalPlane2Top) --
    (ImageFocalPlane2Bottom)}, second line =
  {(LRThroughCenter2Begin) -- (Center2)});
  % 
  \coordinate (Image1Bottom) at
  ($(OpticalAxisLeft)!(Image1Top)!(OpticalAxisRight)$); 
  \coordinate (Image1TopOnLens2) at
  ($(Top2)!(Image1Top)!(Bottom2)$);
  % 
  \draw[LR>] (LRBegin) -- node[above,sloped]
  {$\leftarrow B_{\infty}$} (IncidencePoint);
  \draw[LR>] (IncidencePoint) -- (LRIntersectionWithLens2);
  \draw[dotted] (LRIntersectionWithLens2) -- (Image1Top);
  % 
  \draw[blue,dotted,thick] (ImageFocalPlane2Top) --
  (ImageFocalPlane2Bottom);
  \draw[blue,dotted,thick]
  ($(LRThroughCenter2IntersectionWithImageFocalPlane2)!-1cm!(Center2)$)
  -- (Center2); 
  % 
  \draw[VirtualLR]
  ($(LRThroughCenter2IntersectionWithImageFocalPlane2)!-3cm!
  (LRIntersectionWithLens2)$) -- node[above,sloped,very near start]
  {$\leftarrow B'_{\infty}$} (LRIntersectionWithLens2); 
  \draw[LR>] (LRIntersectionWithLens2) --
  ($(LRIntersectionWithLens2)!-3cm!
  (LRThroughCenter2IntersectionWithImageFocalPlane2)$); 
  % 
  \coordinate (PictureBottomLeft) at (OpticalAxisLeft |-
  Bottom1);
  \coordinate (PictureTopRight) at (OpticalAxisRight |- Top2);
  \draw[ultra thin,semitransparent] ($(PictureBottomLeft)+(0,-.5)$)
  grid[step=1mm] ($(PictureTopRight)+(0,.5)$);
  \draw[very thin,semitransparent] ($(PictureBottomLeft)+(0,-.5)$)
  grid[step=5mm] ($(PictureTopRight)+(0,.5)$);
  \draw[thin,semitransparent] ($(PictureBottomLeft)+(0,-.5)$)
  grid[step=1cm] ($(PictureTopRight)+(0,.5)$);
  % 
  \coordinate (Image1TopOnLens1) at ($(Top1)!(Image1Top)!(Bottom1)$);
  \draw[LR>>] ($(Image1TopOnLens1)!1cm!(ObjectFocus1)$) --
  (Image1TopOnLens1); 
  \draw[LR>>] (Image1TopOnLens1) -- (Image1TopOnLens2);
  \draw[LR>>] (Image1TopOnLens2) -- ($(Image1TopOnLens2)!-.3!(ImageFocus2)$);
  \draw[VirtualLR] (Image1TopOnLens2) --
  ($(Image1TopOnLens2)!2!(ImageFocus2)$); 
  % 
  \tikzMarkAngle[path options={<-,DarkOrange}]%
  (Center1)(LRThroughCenter1Begin)(OpticalAxisLeft){$\alpha$} 
  \tikzMarkAngle[path options={<-,DarkOrange}]%
  (Center1)(Image1Top)(OpticalAxisRight){$\alpha$} 
  \tikzMarkAngle[path options={<-,DarkOrange}]%
  (ImageFocus2)(Image1TopOnLens2)(OpticalAxisRight){$\alpha'$} 
  % 
\end{tikzpicture}

\end{document}

Galileo

share|improve this answer
    
You can get key-dependent anchor names using deferred anchors. I recently came across this and find it pretty interesting. I'll try to have a look soon and see if I can come up with a start to tackling this kind of issue. –  Roelof Spijker Nov 2 '11 at 18:59
2  
@wh1t3 I know, I implemented it! ;-) –  cjorssen Nov 2 '11 at 19:14
    
Thanks for this idea, but I’m looking rather for a library to print the shapes of objects like lenses etc. and not the rays between them. I guess I’ll have to make my own small library … –  Tobi Nov 3 '11 at 17:40
add comment

There is an extensive library in pstricks - maybe it helps. http://www.ctan.org/tex-archive/graphics/pstricks/contrib/pst-optic

share|improve this answer
1  
Thanks Boris but I prefer using TikZ further on … –  Tobi Nov 2 '11 at 17:16
1  
Wow. That's a neat one, good to know! –  percusse Nov 2 '11 at 22:16
add comment
up vote 5 down vote accepted

This is my solution using TikZ with the calc and intersection libraries.

\documentclass{standalone}% or wathever you want

% load packages
\usepackage{tikz, xcolor}
% load libraries
\usetikzlibrary{intersections,shapes.arrows,calc}

% define light and dark gray
\definecolor{lgray}{cmyk}{0,0,0,0.2}
\definecolor{dgray}{cmyk}{0,0,0,0.7}

% make some settings
\tikzset{%
    % style for the intersecting path, which
    % are nessesary for the calculation but
    % shouldn't be drawn in the final image
    ipath/.style={
%       draw,% comment this aout after construction
        red
    },
    % style for an arrow used as object
    optical arrow/.style={%
        fill=dgray,
        inner sep=3pt,
        shape=single arrow,
        minimum width=0.5cm,
        minimum height=1.5cm,
        outer sep=0pt,
        shape border rotate=90,
    },
    % style for the virtual image
    virtual optical arrow/.style={%
        fill=lgray,
        inner sep=3pt,
        shape=single arrow,
        minimum width=0.5cm,
        minimum height=1.5cm,
        outer sep=0pt,
        shape border rotate=90,
    },
    % style for the mirror
    mirror/.style={%
        line width=2pt,
    },
    % style for the axis
    optical axis/.style={%
        thin,
    },
    % style for light rays
    ray/.style={%
        thin,
        ->,
    },
    % style for imagined rays, which ar not real
    % but help by constructin the image
    imagined ray/.style={%
        ray, dgray, -,
    },
    % alias
    virtual ray/.style={imagined ray},
    % style for (focal) points
    point/.style={%
        fill=black,
        radius=0.8pt,
        inner sep=1pt,
        shape=circle,
        minimum size=2pt,
        outer sep=2pt
    },
}

% set three layers
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}
% and define shortcuts to access them
\newcommand{\bglayer}[1]{%
    \begin{pgfonlayer}{background}%
    #1%
    \end{pgfonlayer}%
}
\newcommand{\fglayer}[1]{%
    \begin{pgfonlayer}{foreground}%
    #1%
    \end{pgfonlayer}%
}

\begin{document}
\begin{tikzpicture}
    % define the bounding box is nessesarx because the ipaths
    % make it bigger than needed
    \path [use as bounding box] (-5.2,-5) rectangle (6.2,5);
    % define variables, you may vary them a little
    %% radius
    \def\radius{5}
    \def\radiusII{5.05}
    %% focal distancs = \radius/2
    \def\focal{2.5}
    %% object size
    \def\size{1.cm}
    %% object width
    \def\owidth{1.25}
    % draw mirror
    %% the extra ipath is nessesary to get nicer rays
    \path [ipath, name path=M] (\radius,0) ++(90:\radius)
          arc (90:270:\radius);
    \fglayer{%
        \draw [mirror] (\radiusII-0.05,0) ++(130:\radiusII)
              arc (130:240:\radiusII);
    }
    % draw focal point
    \node (B) at (\focal,0) [point] {};
    % draw object
    \node (O) [optical arrow,anchor=tail, minimum height=\size] %
          at (\owidth,0) {};
    %% description
    \node [above right] at (O.tip) {object};
    % rays
    %% draw axis ray
    \draw [ray] (O.tip) -- (0,0) -- ($(0,0)!3!(\owidth,-\size)$);
    %% draw parallel ray
    \path [ipath, name path=PS] (O.tip) -- ++(-3,0);
    \draw [ray, name intersections={of=M and PS, by=M-PS}]
        (O.tip) -- (M-PS) -- ($(M-PS)!2!(B)$);
    %% caculate virtual axis ray
    \path [ipath, name path=AS-V] ($(0,0)!-4!(\owidth,-\size)$) -- (0,0);
    %% calculate virtual parallel ray
    \path [ipath, name path=PS-V] ($(M-PS)!-4!(B)$) -- (M-PS);
    %% draw virtual axis ray
    \draw [imagined ray, name intersections={of=AS-V and PS-V, by=Tip-V}]
        (Tip-V) -- (0,0);
    %% draw virtual axis ray
    \draw [imagined ray] (Tip-V) -- (M-PS);
    % draw virtual object
    \bglayer{\path let \p{1}=(Tip-V) in 
        (Tip-V) node (V) [minimum height=\size,
                          scale={\y{1}/\size*0.665},
                          virtual optical arrow,anchor=tip
                         ] {};}
    %% description
    \path (V.west) node [left] {virtual image};
    % draw optical axis
    \fglayer{\draw [optical axis] (-5,0) --++(11,0);}
\end{tikzpicture}
\end{document}

width drawn ipaths

final image

share|improve this answer
add comment

Here is an attempt to use the node/shape mecanism to automate the positionning of images of objects by optical system. It is, at the moment, just a proof of concept. Feel free to comment.

enter image description here

\documentclass{standalone}
\usepackage{tikz}

\makeatletter

\tikzset{%
  optics/.is family,
  optics/.cd,
  % Thin centered optical system
  optical system/.is family,
  optical system/.cd,
  image focal length/.initial = 1.5cm,
  object focal length/.initial = -1.5cm,
  upper height/.initial = 1.25cm,
  lower height/.initial = -1.25cm,
}

\tikzset{%
  % Object
  optics/.cd,
  object/.is family,
  object/.cd,
  is object for/.initial = a,
  height/.initial = 1cm,
}

\pgfdeclareshape{thin centered optical system}{%
  \savedmacro\upperheight{%
    \edef\upperheight{%
      \pgfkeysvalueof{%
        /tikz/optics/optical system/upper height}}}
  \savedmacro\lowerheight{%
    \edef\lowerheight{%
      \pgfkeysvalueof{%
        /tikz/optics/optical system/lower height}}}
  \savedmacro\imagefocallength{%
    \edef\imagefocallength{%
      \pgfkeysvalueof{%
        /tikz/optics/optical system/image focal length}}}
  \savedmacro\objectfocallength{%
    \edef\objectfocallength{%
      \pgfkeysvalueof{%
        /tikz/optics/optical system/object focal length}}}
  % Center
  \savedanchor{\centerpoint}{\pgfpointorigin}
  \anchor{center}{\centerpoint}
  % Top
  \savedanchor{\top}{\pgfpoint{0pt}{\upperheight}}
  \anchor{top}{\top}
  % Bottom
  \savedanchor{\bottom}{\pgfpoint{0pt}{\lowerheight}}
  \anchor{bottom}{\bottom}
  % Principal image focus
  \savedanchor{\principalimagefocus}{\pgfpoint{\imagefocallength}{0pt}}
  \anchor{principal image focus}{\principalimagefocus}
  % Principal object focus
  \savedanchor{\principalobjectfocus}{\pgfpoint{\objectfocallength}{0pt}}
  \anchor{principal object focus}{\principalobjectfocus}
  %
  \backgroundpath{%
    \pgfpathmoveto{\bottom}
    \pgfpathlineto{\top}
    \pgfusepath{stroke}
  }
}

\pgfdeclareshape{converging lens}{%
  \savedmacro\upperheight{%
    \edef\upperheight{%
      \pgfkeysvalueof{%
        /tikz/optics/optical system/upper height}}}
  \savedmacro\lowerheight{%
    \edef\lowerheight{%
      \pgfkeysvalueof{%
        /tikz/optics/optical system/lower height}}}
  \savedmacro\imagefocallength{%
    \edef\imagefocallength{%
      \pgfkeysvalueof{%
        /tikz/optics/optical system/image focal length}}}
  \savedmacro\objectfocallength{%
    \pgfmathsetmacro\objectfocallength{-(\imagefocallength)}}
  %
  \inheritsavedanchors[from=thin centered optical system]
  \inheritanchor[from=thin centered optical system]{center}
  \inheritanchor[from=thin centered optical system]{top}
  \inheritanchor[from=thin centered optical system]{bottom}
  \inheritanchor[from=thin centered optical system]{principal image focus}
  \inheritanchor[from=thin centered optical system]{principal object focus}
  %
  \backgroundpath{%
    \pgfsetarrows{stealth-stealth}
    \pgfsetlinewidth{2pt}
    \pgfpathmoveto{\bottom}
    \pgfpathlineto{\top}
  }
}

\pgfdeclareshape{object}{%
  \savedmacro\height{%
    \edef\height{\pgfkeysvalueof{/tikz/optics/object/height}}}
  \savedmacro\isobjectfor{%
    \edef\isobjectfor{%
      \pgfkeysvalueof{/tikz/optics/object/is object for}}}
  \savedmacro\imagefocallength{%
    \begingroup
      \csname pgf@sh@ma@\isobjectfor\endcsname
      \edef\pgf@temp{%
        \endgroup
        \def\noexpand\imagefocallength{\imagefocallength}}%
      \pgf@temp}
  % Bottom
  \savedanchor{\centerpoint}{\pgfpointorigin}
  \anchor{center}{\centerpoint}
  \anchor{bottom}{\centerpoint}
  % Top
  \savedanchor{\top}{\pgfpoint{0pt}{\height}}
  \anchor{top}{\top}
  % Optical system center
  \savedanchor{\opticalsystemcenter}{%
    \pgfpointanchor{\isobjectfor}{center}}
  \anchor{optical system center}{\opticalsystemcenter}
  % Top on optical system
  \savedanchor{\toponopticalsystem}{%
    % This allows to define \savedanchors in terms of other saved anchors.
    \pgf@sh@savedpoints
    \pgfpointdiff{\top}{\opticalsystemcenter}
    \pgf@y=\height}
  \anchor{top on optical system}{\toponopticalsystem}
  % Image top
  \savedanchor{\imagetop}{%
    % This allows to define \savedanchors in terms of other saved anchors.
    \pgf@sh@savedpoints
    \pgfpointintersectionoflines{%
      \toponopticalsystem}{%
      \pgfpointanchor{\isobjectfor}{principal image focus}}{%
      \top}{%
      \pgfpointanchor{\isobjectfor}{center}}}
  \anchor{image top}{\imagetop}
  % Image top on optical system
  \savedanchor{\imagetoponopticalsystem}{%
    % This allows to define \savedanchors in terms of other saved anchors.
    \pgf@sh@savedpoints
    \pgfpointanchor{\isobjectfor}{center}
    \pgf@xa=\the\pgf@x
    \imagetop
    \pgf@x=\the\pgf@xa}
  \anchor{image top on optical system}{\imagetoponopticalsystem}
  %
  \backgroundpath{%
    \pgfsetarrows{-stealth}
    \pgfsetlinewidth{1pt}
    \pgfpathmoveto{\centerpoint}
    \pgfpathlineto{\top}
  }
}

% Light rays

\usetikzlibrary{decorations.markings}

\tikzset{>=stealth}
\pgfarrowsdeclaredouble{doublestealth}{doublestealth}{stealth}{stealth}
\pgfarrowsdeclaretriple{triplestealth}{triplestealth}{stealth}{stealth}
\pgfarrowsdeclarealias{<<}{>>}{doublestealth}{doublestealth}
\pgfarrowsdeclarealias{<<<}{>>>}{triplestealth}{triplestealth}

\tikzset{%
  > = stealth,
  LRnoarrow/.style = {thick,gray,nearly opaque},
  LR/.style 2 args = {%
    decoration = {markings,mark=at position #2 with {\arrow{#1};}},
    postaction = {decorate},
    LRnoarrow},
  VirtualLR/.style = {LRnoarrow,dashed},
  LR>/.style = {LR={>}{#1}},
  LR>/.default = {0.5},
  LR>>/.style = {LR={>>}{#1}},
  LR>>/.default = {0.55},
  LR>>>/.style = {LR={>>>}{#1}},
  LR>>>/.default = {0.6},
}


\makeatother

\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}%[rotate=45,transform shape]
  \node[draw,shape=converging lens,
        optics/optical system/image focal length = 1cm,
        optics/optical system/upper height = 2cm,
        optics/optical system/lower height = -2cm] (L) at (2,0) {};
  %
  \draw[thick,->,-stealth] ($(L)!5cm!90:(L.top)$) coordinate (OpticalAxisLeft) 
        -- ($(L)!5cm!-90:(L.top)$) coordinate (OpticalAxisRight);
  \node[draw,
        shape = object,
        optics/object/is object for = L] (O) at (-1,0) {};
  %
  \fill[red] (L.principal image focus) circle[radius=2pt];
  \fill[blue] (O.optical system center) circle[radius=2pt];
  \fill[green] (O.top on optical system) circle[radius=2pt];
  \fill[yellow] (O.image top) circle[radius=2pt];
  \draw[LR>] (O.top) -- (O.top on optical system) -- (O.image top);
  \draw[LR>>] (O.top) -- (O.image top);
  \draw[LR>>>] (O.top) -- (O.image top on optical system) -- (O.image top);
\end{tikzpicture}

\end{document}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.