6

I drew two blocks stacked on each other. Unfortunately, it looks off and I think it can be done more compactly code wise with a cleaner look.

Here is what I have:

\documentclass[tikz, convert = false]{standalone}%
\usetikzlibrary{calc}
\usetikzlibrary{intersections}

\begin{document}
\begin{tikzpicture}
  \coordinate (O) at (0, 0);
  \coordinate (P1) at (0.35, 1);
  \coordinate (P2) at (1.35, 1);
  \coordinate (P3) at (1, 0);

  \draw (O) -- (P3) node[pos = .5, font = \tiny, below] {$1$} -- (P2)
  node[pos = .5, right, font = \tiny] {$1$};
  \draw[dashed] (O) -- (P1) -- (P2);
  \draw (O) -- +(0, .2) coordinate (P4) -- +(1, .2) coordinate (P5) --
  +(1, 0);
  \draw[name path = uil] (P5) -- ($(P2) + (0, .2)$) coordinate (P6) --
  +(0, -.2);
  \draw (P6) -- +(-1, 0) coordinate (P7);
  \draw[dotted] (P7) -- (P1);

  \path[name path = uol] (P4) -- (P7);
  \path[name path = hl] (0, .35) -- +(1.25, 0);
  \path[name intersections = {of = uol and hl}];

  \coordinate (P8) at (intersection-1);

  \draw[dashed] (P8) -- (P7);
  \draw (P8) -- (P4);

  \path[name intersections = {of = uil and hl}];

  \coordinate (P9) at (intersection-1);

  \draw (P8) -- (P9);
  \draw (P8) -- +(0, .2) coordinate (P10) -- +(1, .2) coordinate (P11) --
  (P9);
  \draw (P6) -- +(0, .2) coordinate (P12);
  \draw (P11) -- (P12) -- +(-1, 0) coordinate (P13) -- (P10);
  \draw[dotted] (P13) -- +(0, -.2);
\end{tikzpicture}
\end{document}

Here is what it looks like (ugly):

enter image description here

How can the code be improved to make a better looking image and to be more simplified?

2 Answers 2

7

Here's an approach which takes perspective into account.

You can modify the dimensions of the boxes by changing the values of the parameters:

\aedepth
\aewidth
\aeheight
\aestepdepth

You can modify the apparent point of view by changing:

\aeeyelevel
\aeLVP
\aeRVP

Here's the code:

\documentclass[tikz,
               convert=false,
               crop=false,
               preview=true,
               border=4pt]{standalone}
\usetikzlibrary{calc}
\usetikzlibrary{intersections}

%% A macro to create the coordinate positions for the corners of the boxes
%% with respect to the positioning of the vanishing points.               
%% #1 plane name                                                          
%% #2 coordinate of corner-stone                                          
%% #3 left side length                                                    
%% #4 right side length                                                   
%% #5 height                                                              
\def\boxlayout#1(#2)#3#4#5{%%
  \coordinate (#1/bot/front)      at (#2);
  \coordinate (#1/bot/side/left)  at ($(#1/bot/front)!#3!(LVP)$);
  \coordinate (#1/bot/side/right) at ($(#1/bot/front)!#4!(RVP)$);

  \begin{pgfinterruptboundingbox}
    \path[name path=#1/bot/line/left] (#1/bot/side/right) -- (LVP);
    \path[name path=#1/bot/line/right] (#1/bot/side/left) -- (RVP);
    \path[name intersections={of=#1/bot/line/left and #1/bot/line/right,by=#1/bot/back}];
  \end{pgfinterruptboundingbox}

  \coordinate (#1/top/front)      at ($(#1/bot/front)+(0,#5)$);

  \begin{pgfinterruptboundingbox}
    \path[name path=#1/top/line/left]  (#1/top/front) -- (LVP);
    \path[name path=#1/vert/line/left] (#1/bot/side/left) -- ++(0,#5);
    \path[name intersections={of=#1/top/line/left and #1/vert/line/left,by=#1/top/side/left}];
    %%
    \path[name path=#1/top/line/right] (#1/top/front) -- (RVP);
    \path[name path=#1/vert/line/right] (#1/bot/side/right) -- ++(0,#5);
    \path[name intersections={of=#1/top/line/right and #1/vert/line/right,by=#1/top/side/right}];
    %%
    \path[name path=#1/top/receding/right]  (#1/top/side/left) -- (RVP);
    \path[name path=#1/top/receding/left]   (#1/top/side/right) -- (LVP);
    \path[name intersections={of=#1/top/receding/right and #1/top/receding/left,by=#1/top/back}];
  \end{pgfinterruptboundingbox}
}

%% change the following parameters to create boxes of different dimensions      
%% this example assumes that the stacked boxes have the same heights.  It should
%% be easy enough to modify the code to change this.                            
\def\aedepth{3cm}
\def\aewidth{4.5cm}
\def\aeheight{1.25cm}
\def\aestepdepth{1.25cm}
%% the macros change the perspective of the viewer.
%% increasing the value of the "eyelevel" gives an increasing bird-eye view.
%% LVP=left vanishing point
%% RVP=right vanishing point
\def\aeeyelevel{5in}
\def\aeLVP{-10in}
\def\aeRVP{15in}

\begin{document}

\begin{tikzpicture}

  \begin{pgfinterruptboundingbox}
    %% Left and right vanishing points
    \coordinate (LVP) at (\aeLVP,\aeeyelevel);
    \coordinate (RVP) at (\aeRVP,\aeeyelevel);
    \draw[red,thin] (LVP) -- (RVP);
  \end{pgfinterruptboundingbox}

  %% constructing the bottom box:
  %% the bottom box's name is "A"
  \boxlayout{A}(0,0){\aedepth}{\aewidth}{\aeheight}

  \begin{pgfinterruptboundingbox}
    %% preparing to construct the top box
    %% the "t" prefix on coordinate names means "temp"
    \coordinate (tB) at ($(A/top/front)+(0,\aeheight)$);
    \coordinate (tC) at ($(A/top/front)!\aestepdepth!(RVP)$);

    \path[name path=tB--RVP] (tB) -- (RVP);
    \path[name path=tC--UP]  (tC) -- ++(0,2cm);
    \path[name intersections={of=tB--RVP and tC--UP,by=tD}];
    %%
    \path[name path=tC--LVP] (tC) -- (LVP);
    \path[name path=TOP--RVP] (A/top/side/left) -- (RVP);
    \path[name intersections={of=tC--LVP and TOP--RVP,by=tE}];

    %% calculating the modified dimensions for the top box by 
    %% taking the perspective into account.
    \path($(tC)-(tE)$);
    \pgfgetlastxy{\aedepthx}{\aedepthy}
    \pgfmathparse{ veclen(\aedepthx,\aedepthy)}
    \global\let\aetopdepth\pgfmathresult
    %%
    \path($(tC)-(tD)$);
    \pgfgetlastxy{\aeheightx}{\aeheighty}
    \pgfmathparse{ veclen(\aeheightx,\aeheighty)}
    \global\let\aetopheight\pgfmathresult
    %%
    \path($(tC)-(A/top/side/right)$);
    \pgfgetlastxy{\aewidthx}{\aewidthy}
    \pgfmathparse{ veclen(\aewidthx,\aewidthy) }
    \global\let\aetopwidth\pgfmathresult
  \end{pgfinterruptboundingbox}

  %% The top box is named "B"
  \boxlayout{B}(tC){\aetopdepth pt}{\aetopwidth pt}{\aetopheight pt}

  %%--------------------------------------------------------------------------------
  %% DRAWING THE BOXES
  %% vertical lines:
  %% bottom box
  \draw[blue]           (A/bot/front)      -- (A/top/front);
  \draw[blue]           (A/bot/side/left)  -- (A/top/side/left);
  \draw[blue]           (A/bot/side/right) -- (A/top/side/right);
  \draw[gray!40,dashed] (A/bot/back)       -- (A/top/back);
  %% top box
  \draw[blue]           (B/bot/front)      -- (B/top/front);
  \draw[blue]           (B/bot/side/left)  -- (B/top/side/left);
  \draw[blue]           (B/bot/side/right) -- (B/top/side/right);
  \draw[gray!40,dashed] (B/bot/back)       -- (B/top/back);
  %% edges
  %% bottom box bottom edge
  \draw [blue]           (A/bot/side/left) -- (A/bot/front) -- (A/bot/side/right);
  \draw [gray!40,dashed] (A/bot/side/left) -- (A/bot/back) -- (A/bot/side/right);
  %% visible top of bottom box
  \draw [blue]           (A/top/side/left) -- 
                         (A/top/front)     --
                         (B/bot/front)     --
                         (B/bot/side/left) -- cycle;

  %% top box top edge
  \draw [blue]           (B/top/side/left) -- (B/top/front) -- (B/top/side/right) -- (B/top/back) -- cycle;
  %% top box bottom edge
  \draw [blue]           (B/bot/side/left) -- (B/bot/front) -- (B/bot/side/right);
  \draw [gray!40,dashed] (B/bot/side/left) -- (B/bot/back)  -- (B/bot/side/right);

\end{tikzpicture}

\end{document}

which produces:

enter image description here

6

Without totally rewriting all the magic numbers, one option would be to add some fill and slightly adjust the unit vectors helps:

enter image description here

Code:

\documentclass[tikz, convert = false, border=2pt]{standalone}%
\usetikzlibrary{calc}
\usetikzlibrary{intersections}

\tikzset{Hidden Line/.style={thin, gray!30}}


\begin{document}
\begin{tikzpicture}[x=1.5cm, y=0.7cm]
  \coordinate (O) at (0, 0);
  \coordinate (P1) at (0.35, 1);
  \coordinate (P2) at (1.35, 1);
  \coordinate (P3) at (1, 0);

  \draw[Hidden Line] (O) -- (P1) -- (P2);
  
  \path (O) -- (P3) node[pos = .5, font = \tiny, below] {$1$};
  
  
  
  \draw [fill=green!25, fill opacity=0.3] (O) -- +(0, .2) coordinate (P4) -- +(1, .2) coordinate (P5) --
      +(1, 0) -- cycle;
      
  \path  (P3) -- (P2)
      node[pos = .5, right, font = \tiny] {$1$}
      ;
  \path[name path = uil, red] (P5) -- ($(P2) + (0, .2)$) coordinate (P6) --
      +(0, -.2);
  \draw [fill=green!25, fill opacity=0.3, join=round]
      ($(P3) +(0, 0.2)$) --
      (P3) -- (P2) --
      ++(0, 0.2) --
      cycle
      ;
      
  \draw [Hidden Line] (P6) -- +(-1, 0) coordinate (P7);
  \draw [Hidden Line] (P7) -- (P1);

  \path[name path = uol] (P4) -- (P7);
  \path[name path = hl] (0, .35) -- +(1.25, 0);
  \path[name intersections = {of = uol and hl}];

  \coordinate (P8) at (intersection-1);

  \draw [Hidden Line] (P8) -- (P7);
  \draw  (P8) -- (P4);

  \path[name intersections = {of = uil and hl}];

  \coordinate (P9) at (intersection-1);

  \path  (P6) -- +(0, .2) coordinate (P12);
  \coordinate (P13) at ($(P12)+(-1, 0)$);
  \draw[Hidden Line, draw opacity=0.8] (P13) -- +(0, -.2);

  \draw [fill=red!40, fill opacity=0.5] (P9) -- (P8)
      (P8) -- +(0, .2) coordinate (P10) -- +(1, .2) coordinate (P11) --
      (P9);
  
  \draw [fill=red!20, fill opacity=0.7, join=round] (P11) -- (P12) -- (P13) -- (P10);
  
  \draw [fill=red!60, fill opacity=0.2, join=round] 
          (P6) -- ++(0, .2) -- 
          (P11) -- ++(0, -.2) -- cycle;
\end{tikzpicture}
\end{document}
2
  • Doesn't the back of the block look like it is wider than the front though? Mine does that too.
    – dustin
    Apr 25, 2014 at 3:34
  • @dustin: Yeah, I think that is because you really need to apply a perspective view where the lines receding into the back are not parallel, but would meet if they were extended out much further. Apr 25, 2014 at 3:41

You must log in to answer this question.

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