59

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

0

7 Answers 7

57

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

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

This answer was converted to its own PGF and its own TikZ library ext.transformations.mirror as part of my tikz-extensions package.


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.

Using built-in transformations.

In response to Turion's comment, I've also implemented a version that only uses existing transformations (shifting, rotating, −1-scaling, rotating back, shifting back).

The macros and keys for this are available with a capital Mirror instead of mirror.

All macros and keys are explained in the respective section of the manual.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{
  backgrounds,
  ext.transformations.mirror % https://ctan.org/pkg/tikz-ext
}
\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

5
  • 2
    Nice generalization!
    – Daniel
    Commented Nov 6, 2013 at 4:17
  • 7
    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
    Commented Apr 21, 2014 at 13:22
  • @Turion I didn't see your comment until now. You're right. In the end, both solutions depend on trigonometic functions, either atan (via \pgfmathanglebetweenpoints) or sin and cos (via \pgfpointnormalized). I have since this answer was posted exported and refined the macros/keys in their own library (see my GitHub). I will implement both and then the user can choose. Commented Aug 13, 2022 at 20:55
  • I don't understand why it cannot just rotate so the simple task is simple Commented Nov 5, 2023 at 11:37
  • @NiklasRosencrantz Hm? Commented Nov 5, 2023 at 13:56
19

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}
\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}
\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}
4
  • @Gaborit, I used your code to mirror the roman analog clock. See the link ( tex.stackexchange.com/questions/568227/…) It does mirror but it creates a duplicate that cannot remove it, otherwise it will not show the mirror image generated. I think it has something to do with the image border. Suggestions?
    – Aschoolar
    Commented Oct 31, 2020 at 14:56
  • Thanks for your code. But loading "decorations.fractals" seems useless (the code runs correct without it). Is there a way to display the reflected image without the source image ?
    – quark67
    Commented May 19, 2021 at 14:14
  • 1
    @quark67 This is not possible because spy duplicates the source image. Commented May 19, 2021 at 20:53
  • OK, good to know. You have forgot to remove the "decorations.fractals" in the second code. Anyway, thanks.
    – quark67
    Commented May 19, 2021 at 21:08
15

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

14

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}
1
  • Mirror other than origin... or Meaning for this code "x={(1,0)},y={(0,-1)}". MWE added.
    – sandu
    Commented Jun 19, 2013 at 9:55
13

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.

8

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

2
  • Simple code, can we mirror along a inclined axis along with text like Qrrbrbirlbel example ? Commented Nov 6, 2013 at 5:40
  • @texenthusiast: Yes. It is not impossible and not difficult. Commented Nov 6, 2013 at 6:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .