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.

I want to draw pictures like this

Originally from wikipedia

or this one

Originally from wikipedia.

It is clear how to do this "manually" with TikZ. However is there a way to do it automatically. I.e. I just want to define the polygon (for example the yellow triangles in the pictures above), a center point Z and a scaling factor m and then get the corresponding picture (as in my examples) automatically generated by that input data.

share|improve this question
    
Why the downvote? –  student Sep 16 '12 at 10:51
    
I assume it is because you didn't show what you've tried so far. This might be seen as a draw-this-for-me question. –  Jake Sep 16 '12 at 18:39

4 Answers 4

Just another solution with PSTricks.

Still Version:

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

\begin{document}

\begin{pspicture}[showgrid](-4,-3)(8,6)
% Setup the original polygon points
\pstGeonode[PosAngle={135,135,135,-45}]
    (2,2){O}
    (4,5){A}
    (6,5){B}
    (7,3){C}
% Setup the image points
\pstHomO[HomCoef=-1.1,PosAngle={315,315,135}]{O}{A,B,C}
% Draw auxiliary lines
\psset{nodesepA=-6,nodesepB=-1,linestyle=dashed,linecolor=gray}
\pstLineAB{O}{A}
\pstLineAB{O}{B}
\pstLineAB{O}{C}
% Draw the polygons
\psset{linestyle=solid,linejoin=2,linecolor=black,fillstyle=solid,opacity=0.25}
\pspolygon[fillcolor=red](A)(B)(C)
\pspolygon[fillcolor=blue](A')(B')(C')
\end{pspicture}

\end{document}

Animated Version:

enter image description here

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

\begin{document}

\multido{\n=0.7+-0.3}{7}{%
\begin{pspicture}[showgrid](-4,-3)(8,6)
% Setup the original polygon points
\pstGeonode[PosAngle={135,135,135,-45}]
    (2,2){O}
    (4,5){A}
    (6,5){B}
    (7,3){C}
% Setup the image points
\FPifgt\n0
\pstHomO[HomCoef=\n,PosAngle={135,135,-45}]{O}{A,B,C}
\else
\pstHomO[HomCoef=\n,PosAngle={315,315,135}]{O}{A,B,C}
\fi
% Draw auxiliary lines
\psset{nodesepA=-6,nodesepB=-1,linestyle=dashed,linecolor=gray}
\pstLineAB{O}{A}
\pstLineAB{O}{B}
\pstLineAB{O}{C}
% Draw the polygons
\psset{linestyle=solid,linejoin=2,linecolor=black,fillstyle=solid,opacity=0.25}
\pspolygon[fillcolor=red](A)(B)(C)
\pspolygon[fillcolor=blue](A')(B')(C')
\end{pspicture}}

\end{document}

Animated version with an image:

enter image description here

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-eucl,multido,graphicx,fp}
\psset{PointName=none,PointSymbol=none}


\def\filename{../../../../../Images/ParisHilton}


\newsavebox\IBox
\savebox\IBox{\includegraphics[scale=0.5]{\filename}}
\psset{xunit=\dimexpr\wd\IBox/8,yunit=\dimexpr\ht\IBox/6}

\begin{document}

\multido{\n=0.80+-0.25}{8}{%
\begin{pspicture}[showgrid](-14,-9)(8,6)
% Setup the original polygon points
\pstGeonode
    (-2,-1){O}
    (8,6){A}
    ([nodesep=-\wd\IBox]A){B}
    ([nodesep=-\wd\IBox,offset=-\ht\IBox]A){C}
    ([offset=-\ht\IBox]A){D}
% Setup the image points
\pstHomO[HomCoef=\n]{O}{A,B,C,D}
% Place the images
\rput[tr](A){\usebox\IBox}
\FPifgt\n0\rput[tr](A'){\scalebox{\n}{\usebox\IBox}}\fi
\FPifeq\n0\relax\fi
\FPiflt\n0\rput[tr](C'){\scalebox{\n}{\usebox\IBox}}\fi
% Draw auxiliary lines
\psset{nodesepA=-6.5,nodesepB=-.25,linestyle=dashed,linecolor=red}
\pstLineAB{O}{A}
\pstLineAB{O}{B}
\pstLineAB{O}{C}
\pstLineAB{O}{D}
\end{pspicture}}

\end{document}
share|improve this answer
    
Hopefully the next built of PSTricks has provided us with a new feature in which the point labels are automatically placed on the angle bisector of the angle in question. –  Who is crazy first Sep 16 '12 at 16:32

Here is a general solution... but not completely since it can not manage the content of nodes (see below for a simpler solution but less general).

I create a new homothety option usable with a path. This options can store the result of an homothetic transformation applied to this path. Some subkeys control the parameters:

  • scale is used to specify the scale (default value: 1).
  • center is used to specify the center (default value: {0,0}).
  • store in is used to specify the macro that stores the transformed path.
  • name is a prefix to name each vertex of the transformed path (default value: homothety).

A little example to show the syntax

\draw[homothety={scale=2,center={1,1},name=A,store in=\transpath}] (0,0) -- (3,4);

As usual, the path is drawn. But in addition:

  • A new path (the original path transformed by the homothety whose scale is 2 and center is (1,1)) is stored in \transpath macro.
  • The vertices of this new path are A-1, A-2, etc.
  • The homothetypoints counter gives the number of vertices.

Then, to draw the transformed path with labels, you can use:

\draw \transpath;
\foreach \num in {1,...,\arabic{homothetypoints}}{
   \node[below] (A-\num) {$A_\num$};
 }

Strengths and limitations

  • You can use homothety just to copy a path (with scale=1 and center={0,0}).
  • The original path can use nodes, coordinates, holes in its definition.
  • Each vertex of the transformed path is stored.
  • But, the content of a node is not transformed...

A larger example (result)

enter image description here

A larger example (long commented code)

\documentclass[margin=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.pathreplacing,decorations.pathmorphing}

\makeatletter
% to produce automaticaly homothetic paths
\newcounter{homothetypoints} % number of vertices of path
\tikzset{
  % homothety is a family...
  homothety/.style={homothety/.cd,#1},
  % ...with some keys
  homothety={
    % parameters
    scale/.store in=\homothety@scale,% scale of current homothetic transformation
    center/.store in=\homothety@center,% center of current homothetic transformation
    name/.store in=\homothety@name,% prefix for named vertices
    % default values
    scale=1,
    center={0,0},
    name=homothety,
    % initialization
    init memoize homothetic path/.code={
      \xdef#1{}
      \setcounter{homothetypoints}{0}
    },
    % incrementation
    ++/.code={\addtocounter{homothetypoints}{1}},
    % a style to store an homothetic transformation of current path into #1 macro
    store in/.style={
      init memoize homothetic path=#1,
      /tikz/postaction={
        decorate,
        decoration={
          show path construction,
          moveto code={
            % apply homothetic transformation to this segment and add result to #1
            \xdef#1{#1 ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentfirst)$)}
            % name this vertex
            \coordinate[homothety/++](\homothety@name-\arabic{homothetypoints})
            at ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentfirst)$);
          },
          lineto code={
            % apply homothetic transformation to this segment and add result to #1
            \xdef#1{#1 -- ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$)}
            % name this vertex
            \coordinate[homothety/++] (\homothety@name-\arabic{homothetypoints})
            at ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$);
          },
          curveto code={
            % apply homothetic transformation to this segment and add result to #1
            \xdef#1{#1
              .. controls ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentsupporta)$)
              and ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentsupportb)$)
              .. ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$)}
            % name this vertex
            \coordinate[homothety/++] (\homothety@name-\arabic{homothetypoints})
            at ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$);
          },
          closepath code={
            % apply homothetic transformation to this segment and add result to #1
            \xdef#1{#1 -- cycle ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$)}
          },
        },
      },
    },
  },
}
\makeatother

\begin{document}
\begin{tikzpicture}[font=\bfseries\sffamily]

  % some styles
  \tikzset{
    dashed line/.style={draw=#1!50!gray,dashed,line width=.4pt},
    filled shape/.style={draw=black,line width=1pt,fill=#1,fill opacity=.4},
    dot/.style={draw,line width=.4pt,fill=#1!50!gray},
  }

  % draw a path (and memomize its definition into \mypath with points named A-1, A-2,...)
  \draw[filled shape=cyan,homothety={store in=\mypath,name=A}]
  (0,0) to[bend right] ++(2,2) -- ++(-1,1) to[bend left] ++(-2,-2) -- cycle;

  % add a label to each vertex
  \pgfmathsetmacro{\nbpoints}{\arabic{homothetypoints}}
  \foreach \num in {1,...,\nbpoints} {
    \node[above] at (A-\num) {$A_\num$};
  }
  % first center: c1
  \fill[dot=green] (0,3) coordinate (c1) circle(2pt) node[right]{$c_1$};
  % store two homothetic transformations of \mypath
  \path[homothety={store in=\secondpath,scale=-1,center=c1}] \mypath;
  \path[homothety={store in=\thirdpath,scale=-2,center=c1,name=B}] \mypath;
  % draw them
  \draw[filled shape=green] \secondpath;
  \draw[filled shape=green] \thirdpath;
  % for each vertex of \thirdpath, add a label and draw a dashed line to
  % corresponding vertex of \mypath
  \foreach \num in {1,...,\nbpoints} {
    \node[below] at (B-\num) {$B_\num$};
    \draw[dashed line=green] (B-\num) -- (A-\num);
  }

  % second center: c2
  \fill[dot=red] (-4,-1) coordinate (c2) circle(2pt) node[above]{$c_2$};
  % store two homothetic transformations of \mypath
  \path[homothety={store in=\secondpath,scale=2,center=c2,name=C}] \mypath;
  \path[homothety={store in=\thirdpath,scale=.5,center=c2}] \mypath;
  % draw them
  \draw[filled shape=red] \secondpath;
  \draw[filled shape=red] \thirdpath;
  % for each vertex of \thirdpath, draw a dashed line to center and add a label
  \foreach \num in {1,...,\nbpoints} {
    \node[above] at (C-\num) {$C_\num$};
    \draw[dashed line=red] (C-\num) -- (c2);
  }
\end{tikzpicture}
\end{document}

Simple solution but with limitations

You can use calc library and scopes with scale and shift options to draw homothetic transformations. It is simple but your path must be defined only by numeric coordinates.

Result:

simple solution

Code (commented):

\documentclass[margin=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
  % some styles
  \tikzset{
    filled shape/.style={draw=black,line width=1pt,fill=#1,fill opacity=.4},
    dot/.style={draw,line width=.4pt,fill=#1!50!gray},
    homothety at/.style args={#1 scaled by #2}{shift={($(#1)!#2!(0,0)$)},scale=#2},
  }
  % path definition (numeric coordinates only!)
  \def\mypath{(0,0) to[bend right] ++(2,2) -- ++(-1,1) to[bend left] ++(-2,-2) -- cycle}
  % draw this path
  \draw[filled shape=cyan] \mypath;
  % center of homothetic transformation
  \fill[dot=green] (-1,2) coordinate (c1) circle(2pt) node[above]{$c_1$};
  % first transformation (scale=-1, center=c1)
  \begin{scope}[homothety at=c1 scaled by -1]
    \draw[filled shape=red] \mypath;
  \end{scope}
  % second transformation (scale=2, center=c1)
  \begin{scope}[homothety at=c1 scaled by 2]
    \draw[filled shape=red] \mypath;
    \draw[dashed] (c1) -- (0,0);
    \draw[dashed] (c1) -- (2,2);
    \draw[dashed] (c1) -- (1,3);
    \draw[dashed] (c1) -- (-1,1);
  \end{scope}
\end{tikzpicture}
\end{document}
share|improve this answer

run with xelatex or latex->dvips->ps2pdf

\documentclass[pstricks,border=15pt]{standalone}
\usepackage{pstricks-add}
\begin{document}

\begin{pspicture}[showgrid](-5,-5)(5,5)
\pspolygon[linecolor=red!60,fillstyle=solid,fillcolor=red!40!white](-2,-3)(-1,-1)(1,-1)%
\psHomothetie(0,0){-1.5}{\pspolygon[linecolor=blue!60,fillstyle=solid,fillcolor=blue!40!white](-2,-3)(-1,-1)(1,-1)}
\psHomothetie(0,0){1.5}{\pspolygon[linecolor=green!60,fillstyle=solid,fillcolor=green!40!white,opacity=0.5](-2,-3)(-1,-1)(1,-1)}
\psset{linestyle=dashed,linewidth=0.5pt}
\psRelLine(0,0)(-2,-3){-1.75}{A'}\psRelLine(0,0)(-2,-3){1.7}{A}
\psRelLine(0,0)(-1,-1){-1.75}{B'}\psRelLine(0,0)(-1,-1){1.7}{B}
\psRelLine(0,0)(1,-1){-1.75}{C'}\psRelLine(0,0)(1,-1){1.7}{C}

\qdisk(0,0){2pt}
\end{pspicture}    

\end{document}

enter image description here

you can use any object for this, not only polygons. Here an example for an image:

enter image description here

share|improve this answer

I now managed to do the following. Any suggestions for improvements?

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}

\newcommand {\defPoly}[3]
{
  \pgfmathsetmacro{\m}{#2};%
  \coordinate (Z) at #3;%
  \draw (Z) circle (1pt);%
  \path \foreach \coord [count=\ni] in {#1} {\coord coordinate (a\ni)};
  \foreach \k [count=\ni] in {#1} {%
    \global\let\nb\ni};

  \draw (a1) \foreach \i in {2,...,\nb} {--(a\i)} --cycle; %
  \foreach \i in {1,...,\nb} {\coordinate (b\i) at ($(Z) + \m*(a\i)-\m*(Z)$);}%

  \draw (b1) \foreach \i in {2,...,\nb} {--(b\i)} -- cycle;%
  \foreach \i in {1,...,\nb}{\draw[dashed] (Z) -- (b\i);\draw[dashed] (Z) -- (a\i);}%

}

\begin{tikzpicture}[]
   \defPoly{(0,0),(2,2),(1,3),(-2,4)}{3}{(-2,2)};
  \end{tikzpicture}
\end{document}

Output:

output

share|improve this answer

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.