12

enter image description here This is an image I draw with tools. But I need to draw it with Tikz. And The 3 squares in the middle, I need to make them looks like 3D stacked with shadow. And the fonts on it, like 'a1', 'a2', ... will also be skewed. I don't know how to draw it, but I daw a sketch by pencil: enter image description here

I hope that I can control the font size, the font is Helvetica. I am not familiar with Tikz, but it is powerful and amazing! I need to draw this graph. Anyone knows how to achieve the 3D image? Looking forward to your replies! Thanks very much!

Excalibur
  • 335
  • 1
  • 10
  • What about using PStricks? – Werner Jul 22 '14 at 13:57
  • Hi @Werner , I never use PStricks. What I use is OmniGraffle. But I want to draw it with LaTeX code and manipulate characters such as shade, square color, font size and so on. – Excalibur Jul 22 '14 at 15:41
  • Hi @Werner , do you know how to use PStricks to implement the effect? I misunderstood the PStricks as a software like PS. Thanks very much! – Excalibur Jul 22 '14 at 21:30

3 Answers3

12

EDITED to show more parametric variations of parameters.

Borrowing from Bruno's definition of \slantbox at Shear transform a "box", I was able to construct the following, using simple stacks of \fcolorboxes. The perspective is completely determined by three parameters: \myrotate (the baseline rotation), \myslant (the slant magnitude or fallback parameter), and the short-stacking gap.

First, I demonstrate some variations on the perspective parameters:

\documentclass{article}
\usepackage{stackengine,xcolor,graphicx}
\newsavebox{\foobox}
\newcommand{\slantbox}[2][.5]{\mbox{%
        \sbox{\foobox}{#2}%
        \hskip\wd\foobox
        \pdfsave
        \pdfsetmatrix{1 0 #1 1}%
        \llap{\usebox{\foobox}}%
        \pdfrestore
}}
\def\mybox#1{\strut\makebox[\baselineskip]{$#1$}}
\def\mycell#1#2{\fcolorbox{black}{#1}{\mybox{#2}}}
\def\makeply#1#2#3{\expandafter\def\csname layer#1\endcsname{%
  \stackunder[-\fboxrule]{%
    \mycell{#3}{#2_1}\kern-\fboxrule\mycell{#3}{#2_3}}{%
    \mycell{#3}{#2_2}\kern-\fboxrule\mycell{#3}{#2_4}}%
  }%
}
\makeply{A}{a}{white}
\makeply{B}{b}{gray!30}
\makeply{C}{c}{gray!60}
\def\tristack{\Shortstack{\rotatebox{\myrotate}{\slantbox[\myslant]{\layerA}}
                          \rotatebox{\myrotate}{\slantbox[\myslant]{\layerB}}
                          \rotatebox{\myrotate}{\slantbox[\myslant]{\layerC}}}
}
\begin{document}
\def\myrotate{0}  \def\myslant{0}    \setstackgap{S}{1ex}  \tristack~~~
\def\myrotate{15} \def\myslant{-.9}  \setstackgap{S}{-5ex} \tristack~~~~~~
\def\myrotate{20} \def\myslant{-1.1} \setstackgap{S}{-7ex} \tristack
\end{document}

enter image description here

In fact, here is a general parametric variation of parameters (note that "Ply C atop stack" means that the stack was drawn as a \Shortunderstack, rather than as a \Shortstack):

enter image description here

And then, here, I try to recreate something like what the author is seeking:

\documentclass{article}
\usepackage{stackengine,xcolor,graphicx}
\newsavebox{\foobox}
\newcommand{\slantbox}[2][.5]{\mbox{%
        \sbox{\foobox}{#2}%
        \hskip\wd\foobox
        \pdfsave
        \pdfsetmatrix{1 0 #1 1}%
        \llap{\usebox{\foobox}}%
        \pdfrestore
}}
\def\mybox#1{\strut\makebox[\baselineskip]{$#1$}}
\def\mycell#1#2{\fcolorbox{black}{#1}{\mybox{#2}}}
\def\makeply#1#2#3{\expandafter\def\csname layer#1\endcsname{%
  \stackunder[-\fboxrule]{%
    \mycell{#3}{#2_1}\kern-\fboxrule\mycell{#3}{#2_3}}{%
    \mycell{#3}{#2_2}\kern-\fboxrule\mycell{#3}{#2_4}}%
  }%
}
\def\tristack{\Shortstack{\rotatebox{\myrotate}{\slantbox[\myslant]{\layerA}}
                          \rotatebox{\myrotate}{\slantbox[\myslant]{\layerB}}
                          \rotatebox{\myrotate}{\slantbox[\myslant]{\layerC}}}
}
\def\makestrip#1#2#3{\expandafter\def\csname strip#1\endcsname{%
    \setstackgap{S}{-\fboxrule}\Shortstack{%
      \mycell{#3}{#2_1} \mycell{#3}{#2_2} \mycell{#3}{#2_3} \mycell{#3}{#2_4}%
    }\kern-\fboxrule}%
}
\def\tristrip{\stripA\stripB\stripC}
\def\makecomponents#1#2#3{\makeply{#1}{#2}{#3}\makestrip{#1}{#2}{#3}}
\makecomponents{A}{a}{white}
\makecomponents{B}{b}{gray!30}
\makecomponents{C}{c}{gray!60}
\begin{document}
\def\myrotate{0}  \def\myslant{0}    \setstackgap{S}{-.2\fboxsep}  
\stackon[10pt]{$M_1$}{\tristack}\hspace{.1cm}
\raisebox{62pt}{\scalebox{2.5}{$\leftarrow$}}\hspace{.1cm}
\def\myrotate{15} \def\myslant{-.9}  \setstackgap{S}{-5ex} 
\stackon[12pt]{$M$}{\tristack}\hspace{.7cm}
\raisebox{62pt}{\scalebox{2.5}{$\rightarrow$}}\hspace{.2cm}
\stackon[25pt]{$M_2$}{\tristrip}
\end{document}

enter image description here

7

I got a bit bored in the end but here is a TikZ implementation of the same mechanism Steven gives in his answer. With TikZ you can access the trafo matrix entries via <x,y>scale and <x,y>slant keys. Due to Helvetica, this needs Lua/XeLatex.

\documentclass{article}
\usepackage{tikz,amsmath,fontspec}
\setsansfont{Helvetica}
\usetikzlibrary{matrix}
% make a generic matrix style
\tikzset{mycell/.style={
  execute at empty cell={\node[draw,font=\sffamily,minimum size=5mm,outer sep=0]{
      #1$_{\text{\pgfmathparse{int(2*(\pgfmatrixcurrentrow-1)+\pgfmatrixcurrentcolumn)}\pgfmathresult}}$
    };},row sep=-\pgflinewidth,column sep=-\pgflinewidth},ampersand replacement=\&,inner sep=0
}
\begin{document}
\begin{tikzpicture}
\foreach \x[count=\xi from 0,evaluate=\xs using 100-50*\xi] in{a,b,c}{
  \matrix[mycell=\x,fill=gray!\xs] at (0,\xi) {\&\\\&\\};}

\begin{scope}[shift={(3cm,5mm)},transform canvas={xslant=-1},transform shape]
  \foreach \x[count=\xi from 0,evaluate=\xs using 100-50*\xi] in{a,b,c}{
      \matrix[mycell=\x,fill=gray!\xs] at (0.75*\xi,0.75*\xi) {\&\\\&\\};}
\end{scope}
\end{tikzpicture}
\end{document}

enter image description here

percusse
  • 157,807
  • Thanks very much @percusse ! Combine your solution with the previous one, both the font and image are perfect! – Excalibur Jul 30 '14 at 05:08
3

A pstricks version using the rich pst-3dplot package:

enter image description here

\documentclass{article}
\usepackage{pst-3dplot,xcolor,multido,graphicx}

\newcommand{\clap}[1]{\makebox[0pt]{#1}}
\newcounter{framenumber}
\newcommand{\preframelabel}{}
\begin{document}

\begin{pspicture}(\textwidth,12)
  \psset{linewidth = .4pt, fillstyle = solid, unit = 0.5, Alpha = 30, Beta = 25, plane = xy}
  \multido{\iBa=1+1,\iBb=12+-4}{3}{%
    \setcounter{framenumber}{0}%
    \expandafter\ifcase\iBa
      \or   \renewcommand{\preframelabel}{a}\psset{fillcolor=white} % 1
      \or   \renewcommand{\preframelabel}{b}\psset{fillcolor=black!10} % 2
      \else \renewcommand{\preframelabel}{c}\psset{fillcolor=black!20}% 3
    \fi%
    \multido{\iC=1+2}{2}{%
      \multido{\iR=\iBb+-2}{2}{%
        \stepcounter{framenumber}%
        \psframe(\iC,\iR)(\numexpr\iC-2\relax,\numexpr\iR+2\relax)%
        \rput(\numexpr\iC-1\relax,\numexpr\iR+1\relax){\preframelabel\theframenumber}
      }%
    }%
  }

  \rput(5,8){\scalebox{3}{$\Leftarrow$}}

  \rput(12,2){\psset{unit=0.7}
    \multido{\iBa=3+-1,\iBb=9+4}{3}{%
      \setcounter{framenumber}{0}%
      \expandafter\ifcase\iBa
        \or   \renewcommand{\preframelabel}{a}\psset{fillcolor=white} % 1
        \or   \renewcommand{\preframelabel}{b}\psset{fillcolor=black!10} % 2
        \else \renewcommand{\preframelabel}{c}\psset{fillcolor=black!20}% 3
      \fi%
      \multido{\iC=5+-4}{2}{%
        \multido{\iR=1+4}{2}{%
          \stepcounter{framenumber}%
          \pstThreeDSquare(\iC,\iR,\iBb)(4,0,0)(0,4,0)%
          \pstPlanePut(\number\numexpr\iC+2\relax,\number\numexpr\iR+2\relax,\iBb){%
            \rotatebox{180}{%
              \clap{%
                \raisebox{-.5\height}{%
                  \scalebox{1.2}{\preframelabel\theframenumber}}}}}
        }%
      }%
    }}

  \rput(16,8){\scalebox{3}{$\Rightarrow$}}

  \multido{\iB=1+1,\iR=20+2}{3}{%
    \setcounter{framenumber}{0}%
    \expandafter\ifcase\iB
      \or   \renewcommand{\preframelabel}{a}\psset{fillcolor=white} % 1
      \or   \renewcommand{\preframelabel}{b}\psset{fillcolor=black!10} % 2
      \else \renewcommand{\preframelabel}{c}\psset{fillcolor=black!20}% 3
    \fi%
    \multido{\iC=10+-2}{4}{%
      \stepcounter{framenumber}%
      \psframe(\iR,\iC)(\numexpr\iR-2\relax,\numexpr\iC+2\relax)%
      \rput(\numexpr\iR-1\relax,\numexpr\iC+1\relax){\preframelabel\theframenumber}
    }%
  }

\end{pspicture}
\end{document}

A similar example is presented in Isometric Tables in LaTeX.

Werner
  • 603,163