5

I tried to adapt the zooming code from https://tex.stackexchange.com/a/457705/21557 to an ellipse, but if I choose the zooming factor high enough there is an obvious mismatch of the tangent position:

enter image description here

How can I make this work? Here is the code:

\documentclass[tikz,border=5mm]{standalone}


\usetikzlibrary{calc,decorations.markings,positioning,angles}
\usepackage{fp}
\usepgflibrary{fixedpointarithmetic}

\tikzset{
tangent/.style={
        decoration={
            markings,% switch on markings
            mark=
                at position #1
                with
                {
                    \coordinate (tangent point-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,0pt);
                    \coordinate (tangent unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (1,0pt);
                    \coordinate (tangent orthogonal unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,1);
                }
        },
        postaction=decorate
    },
    use tangent/.style={
        shift=(tangent point-#1),
        x=(tangent unit vector-#1),
        y=(tangent orthogonal unit vector-#1)
    },
    use tangent/.default=1
  }

\begin{document}
\begin{tikzpicture}[
    % Style for the spy nodes and the connection line
    spy/.style={%
        draw,orange,
        line width=1pt,
        circle,inner sep=0pt,
    },
]
    % Parameters

    %% size of the spy-in nodes
    \def\spyviewersize{4.25cm}

    %% (line width of the spy nodes) / 2
    %% we need this for clipping later
    \def\spyonclipreduce{0.5pt}

    %% first zoom
    %%% factor
    \def\spyfactorI{20}
    %%% spy in point
    \coordinate (spy-in 1) at (8,0);
    %%% spy on point
    \pgfmathsetmacro{\a}{2}
    \pgfmathsetmacro{\b}{1.5}
    \pgfmathsetmacro{\al}{30}
    \coordinate (spy-on 1) at ({\a*cos(\al)},{\b*sin(\al)});% sould be on the curve



    %% the graph/picture
    \def\pik{
      % \draw[tangent={\al/360}] (0,0) circle (3);
      \draw[tangent={\al/360}] plot[domain=0:360,samples=800] ({\a*cos(\x)},{\b*sin(\x)});
      \draw[use tangent,green,thick] (-2,0) -- (2,0) coordinate (XA);
      \draw[use tangent,red] (-2,0.3) -- (2,-0.3) coordinate (XB);
      \node[fill,circle,inner sep=0pt,minimum size=2pt] (P) at
      ({\a*cos(\al)},{\b*sin(\al)}) {};
      \node[right] at (P) {$P$};
    }


    % draw the original picture
    \pik

    % first zoom
    %% spy on node
    \node[spy,minimum size={\spyviewersize/\spyfactorI}] (spy-on node 1) at (spy-on 1) {};
    %% spy in node
    \node[spy,minimum size=\spyviewersize] (spy-in node 1) at (spy-in 1) {};
    \begin{scope}
        \clip (spy-in 1) circle (0.5*\spyviewersize-\spyonclipreduce);
        \pgfmathsetmacro\sI{1/\spyfactorI}
        \begin{scope}[
            shift={($\sI*(spy-in 1)-\sI*(spy-on 1)$)},
            scale around={\spyfactorI:(spy-on 1)},
        ]
        \pik
        %%
        \pic[draw,angle radius=50,fill=blue!50,pic text=$\varphi$]{angle=XB--P--XA};
        %% How to interpret the measure 50 for the angle radius
        \end{scope}
    \end{scope}
    %% connect the nodes
    \draw [spy] (spy-on node 1) -- (spy-in node 1);
\end{tikzpicture}
\end{document}
Julia
  • 1,648

1 Answers1

4

You are using such a nice tangent style which actually computes the relevant point for you, it's called tangent point-1. Why not just using it?

\documentclass[tikz,border=5mm]{standalone}


\usetikzlibrary{calc,decorations.markings,positioning,angles}
\usepackage{fp}
\usepgflibrary{fixedpointarithmetic}

\tikzset{
tangent/.style={
        decoration={
            markings,% switch on markings
            mark=
                at position #1
                with
                {   
                    \coordinate (tangent point-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,0pt);
                    \coordinate (tangent unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (1,0pt);
                    \coordinate (tangent orthogonal unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,1);
                }
        },
        postaction=decorate
    },
    use tangent/.style={
        shift=(tangent point-#1),
        x=(tangent unit vector-#1),
        y=(tangent orthogonal unit vector-#1)
    },
    use tangent/.default=1
  }

\begin{document}
\begin{tikzpicture}[
    % Style for the spy nodes and the connection line
    spy/.style={%
        draw,orange,
        line width=1pt,
        circle,inner sep=0pt,
    },
]
    % Parameters

    %% size of the spy-in nodes
    \def\spyviewersize{4.25cm}

    %% (line width of the spy nodes) / 2
    %% we need this for clipping later
    \def\spyonclipreduce{0.5pt}

    %% first zoom
    %%% factor
    \def\spyfactorI{20}
    %%% spy in point
    \coordinate (spy-in 1) at (8,0);
    %%% spy on point
    \pgfmathsetmacro{\a}{2}
    \pgfmathsetmacro{\b}{1.5}
    \pgfmathsetmacro{\al}{30}
%    \coordinate (spy-on 1) at ({\a*cos(\al)},{\b*sin(\al)});% sould be on the curve



    %% the graph/picture
    \def\pik{
      % \draw[tangent={\al/360}] (0,0) circle (3);
      \draw[tangent={\al/360}] plot[domain=0:360,samples=800] ({\a*cos(\x)},{\b*sin(\x)});
      \draw[use tangent,green,thick] (-2,0) -- (2,0) coordinate (XA);
      \draw[use tangent,red] (-2,0.3) -- (2,-0.3) coordinate (XB);
      \node[fill,circle,inner sep=0pt,minimum size=2pt] (P) at
      (tangent point-1) {};
      \node[right] at (P) {$P$};
    }


    % draw the original picture
    \pik
    \coordinate (spy-on 1) at (tangent point-1);% sould be on the curve
    % first zoom
    %% spy on node
    \node[spy,minimum size={\spyviewersize/\spyfactorI}] (spy-on node 1) at (spy-on 1) {};
    %% spy in node
    \node[spy,minimum size=\spyviewersize] (spy-in node 1) at (spy-in 1) {};
    \begin{scope}
        \clip (spy-in 1) circle (0.5*\spyviewersize-\spyonclipreduce);
        \pgfmathsetmacro\sI{1/\spyfactorI}
        \begin{scope}[
            shift={($\sI*(spy-in 1)-\sI*(spy-on 1)$)},
            scale around={\spyfactorI:(spy-on 1)},
        ]
        \pik
        %%
        \pic[draw,angle radius=50,fill=blue!50]{%
        angle=XB--tangent point-1--XA};
        \coordinate (aux) at (barycentric cs:XA=1,XB=1,tangent point-1=1);
        \node[right=4mm of aux] (phi){$\varphi$};
        \draw[-latex] (phi) to[bend right](aux);
        %% How to interpret the measure 50 for the angle radius
        \end{scope}
    \end{scope}
    %% connect the nodes
    \draw [spy] (spy-on node 1) -- (spy-in node 1);
\end{tikzpicture}
\end{document}

enter image description here

  • Thanks, thats much better, but not yet perfect: If you increase the zoom level to 50 you will see that the point p is no more on the curve. If you increase it further for example to 100 you get a dimension too large error. Do you also know how to fix this two issues? – Julia Nov 01 '18 at 18:33
  • @Julia The way this tangent style, or, more generally, decorations work is to decompose the path in small linear segments. Therefore, this will always be an approximation, and when you zoom too much, you'll see it. The only way to avoid this would be to compute the tangent analytically. Of course, even then you will eventually see that your plot is a collection of 800 points that are collected by lines. –  Nov 01 '18 at 21:11
  • Thats clear, but how can I controll the precision of approximation which determines of how far I can zoom in wihout obvious mismatches? For the case of the plot itself this is just the sample parameter. But what parameter controls the precision in my case? – Julia Nov 01 '18 at 21:19
  • @Julia I guess in the end you will be limited by TeX's precision even if you load fpu since there is an upper bound on the number of samples and so on. You could still write your own tangent style that does not make use of the tangent system that the decorations are using, which will allow you to increase the precision. The next step of sophistication will be to redo the magnification yourself. All of this may be done, but in the very end you may just learn that LaTeX is not computer algebra system. –  Nov 01 '18 at 21:23