40

After drawing a part in TikZ, is it possible to mirror that part with respect to some axis or line?

MWE

 \documentclass{standalone}

 \usepackage{tikz}

 \begin{document}

 \begin{tikzpicture}
 \draw[step=1.0,gray,thin] (0,0) grid (4,3);
 \draw [thick](1,1) -- (0,0) -- (1,2); % Original Image
 \draw [ultra thick,red] (2,0) -- (2,3); %axis
 % code for Mirror Image
 \draw [thick,blue](3,1) -- (4,0) -- (3,2); % Mirror Image
 \end{tikzpicture}

 \end{document}

enter image description here

36

You can use a scope and invert xscale and yscale as a whole. This is just another method of doing what ipsen did. The scope will be useful in reflecting only a part of the image.

\documentclass{article}

\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw (-1,1) -- (0,0) -- (1,1); % Original Image
\begin{scope}[yscale=-1,xscale=1]
  \draw[red] (-1,1) -- (0,0) -- (1,1); % Mirror Image
\end{scope}

\end{tikzpicture}

\end{document}

enter image description here

Update:

You can use xscale/yscale in combination with xshift/yshift to get the desired effect.

\documentclass{standalone}

\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw[step=1.0,gray,thin] (0,0) grid (4,3);
\draw [thick](1,1) -- (0,0) -- (1,2); % Original Image
\draw [ultra thick,red] (2,0) -- (2,3); %axis
% code for Mirror Image
\begin{scope}[xscale=-1,xshift=-4cm]
\draw [thick,blue](1,1) -- (0,0) -- (1,2);  % Mirror Image
\end{scope}
\end{tikzpicture}

\end{document}

enter image description here

  • This code does not work for the image ""\draw (-1,1) -- (0,0) -- (1,2); % Original Image"" – sandu Jun 19 '13 at 9:37
  • @sandhu: did you change both instances? – Matthew Leingang Jun 19 '13 at 9:56
  • @Matthew Leingang Yes – sandu Jun 19 '13 at 9:57
  • @sandu Please see the update. Is that helpful? – user11232 Jun 19 '13 at 10:05
  • @Harish Kumar Yes it works well – sandu Jun 19 '13 at 10:11
23

A generalization: We want to mirror at every possible axis.

But first, a few special cases.

Mirroring along an axis parallel to the x or the y (canvas) axis.

This is doable relative easily as seen in the other answers, as we only need to double the shifting and swapping the direction of the orthogonal axis:

\def\pgftransformxmirror#1{%
  \pgfmathparse{2*(#1)}%
  \pgftransformcm{-1}{0}{0}{1}{\pgfqpoint{+\pgfmathresult pt}{+0pt}}}
\def\pgftransformymirror#1{%
   \pgfmathparse{2*(#1)}%
   \pgftransformcm{1}{0}{0}{-1}{\pgfqpoint{+0pt}{+\pgfmathresult pt}}}

The TikZ keys xmirror and ymirror are wrapper for these PGF macros. They accept

  • a dimension (with units) which is directly used as the x or y value.
  • a value (without units) which is thrown into \pgfpointxy. Note that the transformation is still applied to the canvas system!
  • a coordinate wrapped in ( … ) which is evaluated and its x or y value is forwarded to the PGF macros. Note that this also only applies to a transformation of the canvas. Mirroring the coordinate (0, 2) at (0, 1) does not necessary lead to the (unmirrored) coordinate (0, 0).

Mirroring along an axis through the origin.

The formula for this transformation is taken from Wikipedia’s page Transformation matrix (section Reflection) and is

enter image description here

or in TeX:

\def\pgftransformmirror#1{%
  \pgfpointnormalised{#1}%
  \pgf@xa=\pgf@sys@tonumber\pgf@y\pgf@x
  \pgf@xb=\pgf@sys@tonumber\pgf@x\pgf@x
  \pgf@yb=\pgf@sys@tonumber\pgf@y\pgf@y
  \multiply\pgf@xa2\relax
  \pgf@xc=-\pgf@yb\advance\pgf@xc\pgf@xb
  \pgf@yc=-\pgf@xb\advance\pgf@yc\pgf@yb
  \edef\pgf@temp{{\the\pgf@xc}{+\the\pgf@xa}{+\the\pgf@xa}{+\the\pgf@yc}}%
  \expandafter\pgf@transformcm\pgf@temp{\pgfpointorigin}}

At the start of the definition the point #1 is normalized (that reflects the fraction) and at the end of the calculations

  • \pgf@xa holds the normalized value 2lxly,
  • \pgf@xc holds the normalized value lx2ly2 and
  • \pgf@yc holds the normalized value ly2lx2.

Finally: Mirroring along any axis.

This formula is loosely based on another Wikipedia article, namely Spiegelungsmatrix (yes, that’s German) and the transformation is reduced to

  • shifting to one of the points on the axis,
  • mirroring along an axis to the origin and
  • shifting the origin back.

The TikZ key mirror can deal with both the cases “axis through origin” and “any axis”.

If it encounters -- in its argument, the code for any axis is executed, otherwise it is assumed to be a coordinate and the code for an axis through the origin is executed.

Possible Improvements

While the xmirror and ymirror cases are very basic simplifcations of the general reflection, the difference between reflection along any axis and an axis through the origin isn’t that big after all, maybe these two cases can be consolidated under one macro.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{backgrounds}
\makeatletter
\tikzset{
  mirror/.code={\pgfutil@in@{--}{#1}\ifpgfutil@in@\tikz@trans@mirror#1\@nil
    \else\tikz@scan@one@point\pgftransformmirror#1\relax\fi},
  ymirror/.code={\pgfutil@ifnextchar(\tikz@trans@ymirror@coordinate\tikz@trans@ymirror@simple#1\@nil},
  xmirror/.code={\pgfutil@ifnextchar(\tikz@trans@xmirror@coordinate\tikz@trans@xmirror@simple#1\@nil}}
\def\tikz@trans@mirror#1--#2\@nil{%
  \pgfextract@process\pgf@trans@mirror@A{\tikz@scan@one@point\pgfutil@firstofone#1}%
  \pgfextract@process\pgf@trans@mirror@B{\tikz@scan@one@point\pgfutil@firstofone#2}%
  \pgftransformMirror{\pgf@trans@mirror@A}{\pgf@trans@mirror@B}}
\def\pgftransformxmirror#1{\pgfmathparse{2*(#1)}\pgftransformcm{-1}{0}{0}{1}{\pgfqpoint{+\pgfmathresult pt}{+0pt}}}
\def\pgftransformymirror#1{\pgfmathparse{2*(#1)}\pgftransformcm{1}{0}{0}{-1}{\pgfqpoint{+0pt}{+\pgfmathresult pt}}}
\def\tikz@trans@ymirror@simple#1\@nil{
  \pgfmathparse{#1}\let\tikz@temp\pgfmathresult
  \ifpgfmathunitsdeclared
    \pgftransformymirror{\tikz@temp pt}%
  \else
    \pgf@process{\pgfpointxy{0}{\tikz@temp}}%
    \pgftransformymirror{+\the\pgf@y}%
  \fi}
\def\tikz@trans@xmirror@simple#1\@nil{
  \pgfmathparse{#1}\let\tikz@temp\pgfmathresult
  \ifpgfmathunitsdeclared
    \pgftransformxmirror{\tikz@temp pt}%
  \else
    \pgf@process{\pgfpointxy{\tikz@temp}{0}}%
    \pgftransformxmirror{+\the\pgf@x}%
  \fi}
\def\tikz@trans@xmirror@coordinate#1\@nil{\tikz@scan@one@point\pgfutil@firstofone#1\pgftransformxmirror{+\the\pgf@x}}
\def\tikz@trans@ymirror@coordinate#1\@nil{\tikz@scan@one@point\pgfutil@firstofone#1\pgftransformymirror{+\the\pgf@y}}
\def\pgftransformmirror#1{%
  \pgfpointnormalised{#1}%
  \pgf@xa=\pgf@sys@tonumber\pgf@y\pgf@x
  \pgf@xb=\pgf@sys@tonumber\pgf@x\pgf@x
  \pgf@yb=\pgf@sys@tonumber\pgf@y\pgf@y
  \multiply\pgf@xa2\relax
  \pgf@xc=-\pgf@yb\advance\pgf@xc\pgf@xb
  \pgf@yc=-\pgf@xb\advance\pgf@yc\pgf@yb
  \edef\pgf@temp{{\the\pgf@xc}{+\the\pgf@xa}{+\the\pgf@xa}{+\the\pgf@yc}}%
  \expandafter\pgf@transformcm\pgf@temp{\pgfpointorigin}}
\def\pgftransformMirror#1#2{%
  \pgfextract@process\pgf@trans@mirror@A{#1}%
  \pgfextract@process\pgf@trans@mirror@B{#2}%
  \pgfextract@process\pgf@trans@mirror@g{\pgfpointdiff{\pgf@trans@mirror@A}{\pgf@trans@mirror@B}}%
  \pgftransformshift{\pgf@trans@mirror@A}%
  \pgftransformmirror{\pgf@trans@mirror@g}%
  \pgftransformshift{\pgfpointscale{-1}{\pgf@trans@mirror@A}}}
\makeatother
\tikzset{every picture/.append style={gridded, line join=round, line cap=round}}
\begin{document}
\begin{tikzpicture}
\draw[thick]       (1,1) -- (0,0) -- (1,2);
\draw[ultra thick, red] (2,0) coordinate (@1) -- node[above,sloped] {Mirror} (2,3) coordinate (@2);
\begin{scope}[mirror=(@1)--(@2)]
  \draw[thick, blue] (1,1) -- (0,0) -- (1,2);
  \path[transform shape] (@1) -- node[above,sloped] {Mirror} (@2);
\end{scope}
\end{tikzpicture}
\begin{tikzpicture}
\draw[thick]       (1,1) -- (0,0) -- (1,2);
\draw[ultra thick, red] (2,0) coordinate (@1) -- node[above,sloped] {Mirror} (2,3) coordinate (@2);
\begin{scope}[xmirror=2]
  \draw[thick, blue] (1,1) -- (0,0) -- (1,2);
  \path[transform shape] (@1) -- node[above,sloped] {Mirror} (@2);
\end{scope}
\end{tikzpicture}
\begin{tikzpicture}\pgfmathsetseed{7}
\draw[thick]       (1,1) -- (0,0) -- (1,2);
\draw[ultra thick, red] (5*rand,5*rand) coordinate (@1) -- node[above,sloped] {Mirror} (5*rand,5*rand) coordinate (@2);
\begin{scope}[mirror=(@1)--(@2)]
  \draw[thick, blue] (1,1) -- (0,0) -- (1,2);
  \path[transform shape] (@1) -- node[above,sloped] {Mirror} (@2);
\end{scope}
\end{tikzpicture}
\end{document}

Output

enter image description hereenter image description here enter image description here

  • 1
    Nice generalization! – Daniel Nov 6 '13 at 4:17
  • 4
    Instead of reimplementing that from scratch, one could combine the xscale=-1-approach with another builtin coordinate transformation, rotate around. First rotate the image such that the mirror axis is vertical, apply xscale=-1, rotate back. – Turion Apr 21 '14 at 13:22
14

Here is a solution via spy library of TikZ.

To mirror a picture, make a scope using mirror scope and its two subkeys:

  • center to define the position of the mirror,

  • angle to define the direction of the mirror.

Draw your picture into this scope then call \mirror.

(Note: the bounding box of the tikzpicture don't take into account the mirrored picture.)

Example:

enter image description here

\documentclass[tikz]{standalone}
\usetikzlibrary{spy,decorations.fractals}
\tikzset{
  mirror scope/.is family,
  mirror scope/angle/.store in=\mirrorangle,
  mirror scope/center/.store in=\mirrorcenter,
  mirror setup/.code={\tikzset{mirror scope/.cd,#1}},
  mirror scope/.style={mirror setup={#1},spy scope={
      rectangle,lens={rotate=\mirrorangle,yscale=-1,rotate=-1*\mirrorangle},size=80cm}},
}
\newcommand\mirror[1][]{\spy[overlay,#1] on (\mirrorcenter) in node at (\mirrorcenter)}

\begin{document}
\begin{tikzpicture}
  \draw [help lines] (-2,0) grid (2,2);
  \begin{scope}[mirror scope={center={0,0},angle=90}]
    \draw[green] (0,0) -- (2,2);
    \draw[red] (1,0) -- (2,2);
    \node[blue,rotate=30] at (1,.5){Mirror};
    \mirror;
  \end{scope}
\end{tikzpicture}
\end{document}

An animated example:

enter image description here

\documentclass[tikz]{standalone}
\usetikzlibrary{spy,decorations.fractals}
\tikzset{
  mirror scope/.is family,
  mirror scope/angle/.store in=\mirrorangle,
  mirror scope/center/.store in=\mirrorcenter,
  mirror setup/.code={\tikzset{mirror scope/.cd,#1}},
  mirror scope/.style={mirror setup={#1},spy scope={
      rectangle,lens={rotate=\mirrorangle,yscale=-1,rotate=-1*\mirrorangle},size=80cm}},
}
\newcommand\mirror[1][]{\spy[overlay,#1] on (\mirrorcenter) in node at (\mirrorcenter)}

\begin{document}
\foreach \myangle in {0,5,...,175}{
  \begin{tikzpicture}
    \fill[white] (-2.1,-2.1) rectangle (2.1,2.1);
    \draw [help lines] (-2,-2) grid (2,2);
    \draw[orange] (0,0) -- ++(\myangle:2cm) -- ++(\myangle:-4cm);
    \begin{scope}[mirror scope={angle=\myangle,center={0,0}}]
      \draw[green] (0,0) -- (2,2);
      \draw[red] (2,1) -- (1,0);
      \node[blue,rotate=30] at (1,.5){Mirror};
      \mirror;
    \end{scope}
  \end{tikzpicture}
}
\end{document}
12

You could for instance change the coordinates in order to obtain the mirror effect. Reflecting vertically about the line going through origo could be obtained by a coordinate change like

\documentclass{article}

\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw (-1,1) -- (0,0) -- (1,1); % Original Image
\draw[red, x={(1,0)},y={(0,-1)}] (-1,1) -- (0,0) -- (1,1); % Mirror Image
\end{tikzpicture}

\end{document}

By the way, if you're more specific about what you want, then you might even get a more specific answer ;-)

Update:

Kumar is somewhat faster than me ;-), but yes can reflect about any point by a combination of the above given procedure and a translation. In your example you will have

\documentclass{article}

\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw[step=1.0,gray,thin] (0,0) grid (4,3);
\draw [thick](1,1) -- (0,0) -- (1,2); % Original Image
\draw [ultra thick,red] (2,0) -- (2,3); %axis
% code for Mirror Image
\draw [thick,blue,x={(-1,0)},y={(0,1)},xshift=4cm](1,1) -- (0,0) -- (1,2); % Mirror Image
\end{tikzpicture}

\end{document}
  • Mirror other than origin... or Meaning for this code "x={(1,0)},y={(0,-1)}". MWE added. – sandu Jun 19 '13 at 9:55
12

Although an answer has been accepted, I will submit my solution. It uses the environ package and the path only has to be entered once. The example code is

\documentclass[border=5pt]{standalone}

\usepackage{tikz}
\usepackage{environ}

\NewEnviron{reverse}[2]{
\BODY
\begin{scope}[xscale= #1,yscale=#2]\BODY\end{scope}}

\begin{document}

\begin{tikzpicture}

\begin{reverse}{1}{-1}
\draw (-1,1) -- (0,0.5) -- (1,1);
\end{reverse}

\end{tikzpicture}

\end{document}

The result is

enter image description here

11

There are two types of mirroring operation you might want to perform. One just transforming the reference coordinates, the other also mirror the content. The pgfmanual calls the first "coordinate transformations" and the second "canvas transformations". To avoid coding the image twice you can use a foreach loop together with some scoping. I have added label to your diagram to demonstrate the difference.

Sample output

\documentclass{article}

\usepackage{tikz}

\begin{document}

\subsection*{Coordinate transformation}

\begin{tikzpicture}
  \draw[step=1.0,gray,thin] (0,0) grid (4,3);
  \draw[ultra thick,red] (2,0) -- (2,3); %axis
  \foreach \xsc/\xsh/\col in {1/0/black,-1/-4/blue} {
  \begin{scope}[\col,xscale=\xsc,xshift=\xsh cm]
    \draw [thick] (1,1) -- (0,0) node[left] {P} -- (1,2);
  \end{scope}
  };
\end{tikzpicture}

\subsection*{Canvas transforamtion}

\begin{tikzpicture}
  \draw[step=1.0,gray,thin] (0,0) grid (4,3);
  \draw[ultra thick,red] (2,0) -- (2,3); %axis
  \foreach \xsc/\xsh/\col in {1/0/black,-1/-4/blue} {
    \pgflowlevelscope{\pgftransformxscale{\xsc}\pgftransformxshift{\xsh cm}}
    \draw [thick,\col] (1,1) -- (0,0) node[left] {P} -- (1,2);
    \endpgflowlevelscope ;
  };
\end{tikzpicture}

\end{document}

In the first example the scope is uncesseary, the xscale / xshift could just be passed to the single \draw statement, but if you image is more complicated then such a scope is useful.

The images are shifted because the computed bounding boxes are different.

9

With PSTricks:

\documentclass[pstricks,border=12pt]{standalone}
\begin{document}
\begin{pspicture}[showgrid=true](-2,0)(2,3)
    \psline[linecolor=red](0,0)(0,3)
    \def\obj#1{\psline[linecolor=#1](1,1)(2,0)(1,2)}% necessary comment!
    \obj{blue}
    \psscalebox{-1 1}{\obj{black}}% x-scale y-scale
\end{pspicture}
\end{document} 

enter image description here

Slanted Mirror

For a slanted mirror, we can do as follows.

\documentclass[pstricks,border=12pt]{standalone}
\begin{document}    
\newcommand\object[1][red]{{\psline[linecolor=#1]{->}(1,1)(3,1)(1,2)\rput[b](2,0){\textcolor{#1}{Marienplatz}}}}

\begin{pspicture}(5,5)
    \rput{45}(1,1){\object[blue]\psline(5,0)\psscalebox{1 -1}{\object}}
\end{pspicture}
\end{document}

enter image description here

Or for more sophisticated method, use pst-eucl.

Miscellaneous

The application of reflection in our daily life.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-grad}

% Define a new style
\newpsstyle{batman}
{
    fillstyle=gradient,
    gradbegin=red,
    gradend=yellow,
    gradangle=30,
    gradmidpoint=0.5,
    linewidth=6pt,
}

% Define a PostScript operator to convert an elliptical point
% "a b Θ" to its Cartesian "x y"
\pstVerb{/p2c {dup 3 1 roll cos mul 3 1 roll sin mul} bind def}

% Define the right part of Batman
\def\RightPart
{
    % start from ear to tail
    \psline(.5,2.7)(1,3.25)
    \psbezier(1.2,1.3)(1.3,1)(2,1)
    \psbezier(3,1)(3,2.2)(!3.3 6 72 p2c)
    \psellipticarcn(6,3.3){(!3.3 6 72 p2c)}{(!3.3 6 72 neg p2c)}
    \psbezier(4,-2)(4,0)(2.2,-1.8)
    \psbezier(1.5,-1)(1,-1)(0,-3.2)
}


\begin{document}

\begin{pspicture}[dimen=m](-7,-4)(7,4)
% Drawing order: tail, right wing, right ear, left ear, left wing, tail.
\pscustom[style=batman]
{
    % reverse the right part so the drawing starts from the tail to the right wing followed by the right ear 
    \RightPart
    \reversepath
    % reflect the right part for the left part so the drawing is continued to the left ear followed by the left wing
    \scale{-1 1}
    \RightPart
    % close path so the drawing ends at the tail
    \closepath
}
\end{pspicture}

\end{document}

enter image description here

  • Simple code, can we mirror along a inclined axis along with text like Qrrbrbirlbel example ? – texenthusiast Nov 6 '13 at 5:40
  • @texenthusiast: Yes. It is not impossible and not difficult. – kiss my armpit Nov 6 '13 at 6:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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