我画了两个相互叠在一起的方块。不幸的是,它看起来不太对劲,我认为可以用更紧凑的代码来实现,看起来更干净。
以下是我所拥有的:
\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}
它看起来是这样的(丑陋的):
如何改进代码以使图像看起来更好并且更加简化?
答案1
这是一种看法考虑在内。
您可以通过改变参数的值来修改盒子的尺寸:
\aedepth
\aewidth
\aeheight
\aestepdepth
您可以通过改变以下内容来修改明显的观点:
\aeeyelevel
\aeLVP
\aeRVP
代码如下:
\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}
生成结果:
答案2
如果不完全重写所有的魔法数字,一个选项是添加一些填充并稍微调整单位向量有帮助:
代码:
\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}