我正在尝试申请Tikz-dimline 标签位置(尺寸线)到三维绘图。这在 2D 中对我来说效果很好,所以我想在 3D 中也会如此。
因此,在 2D 绘图中,我会使用类似
\draw [postaction={indicate dimensions={$2$}}] (C) -- (G);
它应该在 3D 中使用时
\begin{scope}[canvas is xy plane at z=\Height]
\draw [postaction={indicate dimensions={$2$}}] (C) -- (G);
\end{scope}
但是,上述两种方法得到的结果完全相同(图中黑色尺寸线)。近似所需结果以红色显示。
修改尺寸代码的最简单方法是什么Tikz-dimline 标签位置(尺寸线),或者我如何使用它在 3D 环境中工作?
笔记:
我非常希望改变我调用代码的方式(而不是改变现有的代码
dimline
),因为现有的代码对于 2D 情况来说运行良好。红色部分为期望结果近似以免使此处发布的图形混乱(尺寸箭头线从尺寸标记的末端移开)。
代码看起来比较长,主要是因为网格和轴图的包装。相关部分实际上位于顶部(尺寸代码)和范围的末尾
canvas is xy plane at z=\Height
。
代码:
\documentclass{article}
\usepackage{xparse}
\usepackage{tikz}
\usetikzlibrary{3d}
\pagecolor{white}
%% ---------------------------------------------------------------------
%% https://tex.stackexchange.com/a/468144/4301
\usetikzlibrary{calc,decorations.pathreplacing,arrows.meta}
\newif\ifdrawdimlineleft
\newif\ifdrawdimlineright
\tikzset{dimlabel distance/.initial=5mm,
vertical lines extend/.initial=5mm,
vertical dim line/.style={gray,thin},
dim arrow line/.style={latex-latex,thin},
dim label/.style={},
left dimline/.is if=drawdimlineleft,
left dimline=true,
right dimline/.is if=drawdimlineright,
right dimline=true,
indicate dimensions/.style={decorate,decoration={
show path construction,
lineto code={
\draw[dim arrow line]
($ (\tikzinputsegmentfirst)!\pgfkeysvalueof{/tikz/dimlabel distance}!-90:(\tikzinputsegmentlast) $) -- ($ (\tikzinputsegmentlast)!\pgfkeysvalueof{/tikz/dimlabel distance}!90:(\tikzinputsegmentfirst) $)
\ifx#1\empty
\else
node[midway,sloped,fill=white,dim label]{#1}
\fi;
\ifdrawdimlineleft
\draw[vertical dim line] (\tikzinputsegmentfirst) --
($ (\tikzinputsegmentfirst)!\pgfkeysvalueof{/tikz/vertical lines
extend}!-90:(\tikzinputsegmentlast) $);
\fi
\ifdrawdimlineright
\draw[vertical dim line] (\tikzinputsegmentlast) --
($ (\tikzinputsegmentlast)!\pgfkeysvalueof{/tikz/vertical lines extend}!90:(\tikzinputsegmentfirst) $);
\fi
}}}}
%% ---------------------------------------------------------------------
\NewDocumentCommand{\DrawCoordinateGrid}{O{} m m m m m m}{%
\def\XGridMin{#2}
\def\XGridMax{#3}
\def\YGridMin{#4}
\def\YGridMax{#5}
\def\ZGridMin{#6}
\def\ZGridMax{#7}
%
\begin{scope}[canvas is xy plane at z=0, ultra thin, gray!75]
\draw [#1] (\XGridMin,\YGridMin) grid (\XGridMax,\YGridMax);
\end{scope}
\begin{scope}[canvas is yz plane at x=0, ultra thin, gray!75]
\draw [#1] (\YGridMin,\ZGridMin) grid (\YGridMax,\ZGridMax);
\end{scope}
\begin{scope}[canvas is xz plane at y=0, ultra thin, gray!75]
\draw [#1] (\XGridMin,\ZGridMin) grid (\XGridMax,\ZGridMax);
\end{scope}
}%
\NewDocumentCommand{\DrawCoordinateAxis}{O{} m m m m m m}{%
\def\XAxisMin{#2}
\def\XAxisMax{#3}
\def\YAxisMin{#4}
\def\YAxisMax{#5}
\def\ZAxisMin{#6}
\def\ZAxisMax{#7}
%
\begin{scope}[thin, gray, -latex]
\draw [#1] (\XAxisMin,0,0) -- (\XAxisMax,0,0) node [below left] {$x$};
\draw [#1] (0,\YAxisMin,0) -- (0,\YAxisMax,0) node [right] {$y$};
\draw [#1] (0,0,\ZAxisMin) -- (0,0,\ZAxisMax) node [above] {$z$};
\end{scope}
}%
\newcommand*\Width{2.5}%
\newcommand*\Depth{4.5}%
\newcommand*\Height{2.0}%
\tikzset{Line Style/.style={draw=brown, ultra thick, join=round}}
\begin{document}
\begin{tikzpicture}[
x={(-0.5cm,-0.5cm)},
y={(0.9659cm,-0.25882cm)},
z={(0cm,1cm)},
]
\coordinate (O) at (0,0,0);
%% ---------------------------------------------- yz plane at x=0
\coordinate (A) at (0,\Width,0);
\coordinate (B) at (0,\Width,\Height);
\coordinate (C) at (0,0,\Height);
%% ---------------------------------------------- yz plane at x=\Depth
\coordinate (D) at (\Depth,0,0);
\coordinate (E) at (\Depth,\Width,0);
\coordinate (F) at (\Depth,\Width,\Height);
\coordinate (G) at (\Depth,0,\Height);
\DrawCoordinateGrid{0}{6}{0}{4}{0}{3}
\DrawCoordinateAxis[thick, black]{0}{6.5}{0}{4.5}{0}{3.5}
%% ------------------------------------ Draw the rectangular prism
\draw [Line Style] (O) -- (A) -- (B) -- (C) -- cycle;% yz plane at x=0
\draw [Line Style] (D) -- (E) -- (F) -- (G) -- cycle;% yz plane at x=\Depth
\draw [Line Style] (O) -- (D) -- (G) -- (C) -- cycle;% xz plane at y=0
\draw [Line Style] (A) -- (E) -- (F) -- (B) -- cycle;% xz plane at y=\Width
%% This produces the same if it is within a "canvas is xy plane at z=\Height" scope
%\draw [postaction={indicate dimensions={$2$}}] (C) -- (G);
\begin{scope}[canvas is xy plane at z=\Height, inner sep=0pt]
\draw [postaction={indicate dimensions={$2$}}] (C) -- (G);
\end{scope}
%% This is what I expected from the above scope:
\begin{scope}[canvas is xy plane at z=\Height, transform shape, inner sep=2pt, red]
\draw (C) -- ([yshift=-5mm]C);
\draw (G) -- ([yshift=-5mm]G);
\draw [latex-latex] ([yshift=-3mm]C) -- ([yshift=-3mm]G)
node [pos=0.5, xscale=-1, yscale=-1, fill=white] {$2$};
\end{scope}
%% Following is for debugging purposes so you can see where the points are
%% These are last so that they show up on top
\foreach \xy in {O, A, B, C, D, E, F, G}{
\node at (\xy) {\tiny\xy};
}
\end{tikzpicture}
\end{document}
答案1
我首先从你的问题开始,修改尺寸代码或如何使用它在 3D 中工作最简单的方法是什么? 我建议进行两项改变以实现您的目标:
- 对 2D 绘图使用相同的代码
- 3D 绘图中,尺寸元素位于所需平面中。
的初始代码indicate dimensions
相对于要测量的线段方向顺时针旋转 90 度。这在 2D 绘图中没有问题,但在 3D 中则不行(因为计算pgf
使用的是 2D 点,因此角度始终被视为 90 度屏幕上)。
答案。
为了解决这个问题,我引入了一个 pgf 键,angleshift
,默认值为 0。在 3D 绘图时,只需修改其值即可(例如在scope
准备调用 的命令中indicate dimensions
)。angleshift
执行逆时针旋转。
现在,关于代码中的修改:angleshift
用于修改
- 转弯角度
- 打印参数的文本的方向(将其包含在所需的平面中)
- 箭头的尖端(使它们属于所需的平面,如上例中的 3)。
代码。 这主要是您的代码,并带有我所描述的小修改。它们以 标记% modification <something>
。
\documentclass[11pt, margin=1cm]{standalone}
\usepackage{xparse}
\usepackage{tikz}
\usetikzlibrary{3d}
%% ---------------------------------------------------------------------
%% https://tex.stackexchange.com/a/468144/4301
\usetikzlibrary{calc, decorations.pathreplacing, arrows.meta}
\newif\ifdrawdimlineleft
\newif\ifdrawdimlineright
\pgfkeys{/tikz/.cd, % modification angleshift definition
angleshift/.store in=\angleshift,
angleshift=0
}
\tikzset{%
dimlabel distance/.initial=5mm,
vertical lines extend/.initial=5mm,
vertical dim line/.style={gray, thin},
dim arrow line/.style={% % modification tip
arrows={latex[slant={-sin(\angleshift)}]-latex[slant={-sin(\angleshift)}]},
thin
},
dim label/.style={},
left dimline/.is if=drawdimlineleft,
left dimline=true,
right dimline/.is if=drawdimlineright,
right dimline=true,
indicate dimensions/.style={%
decorate, decoration={%
show path construction,
lineto code={%
\draw[dim arrow line] % modification arrow line
($(\tikzinputsegmentfirst)!\pgfkeysvalueof{/tikz/dimlabel distance}!
{-90+\angleshift}:(\tikzinputsegmentlast) $)
-- ($ (\tikzinputsegmentlast)!\pgfkeysvalueof{/tikz/dimlabel distance}!
{90+\angleshift}:(\tikzinputsegmentfirst) $)
\ifx#1\empty
\else % modification text
node[midway, fill=white, dim label,
sloped, xslant={-sin(\angleshift)}, scale=.8]{#1}
\fi;
\ifdrawdimlineleft % modification vertical dim line
\draw[vertical dim line] (\tikzinputsegmentfirst) --
($ (\tikzinputsegmentfirst)!\pgfkeysvalueof{/tikz/vertical lines
extend}!{-90+\angleshift}:(\tikzinputsegmentlast) $);
\fi
\ifdrawdimlineright
\draw[vertical dim line] (\tikzinputsegmentlast) --
($ (\tikzinputsegmentlast)!\pgfkeysvalueof{/tikz/vertical
lines extend}!{90+\angleshift}:(\tikzinputsegmentfirst) $);
\fi
}
}
}
}
%% ---------------------------------------------------------------------
\NewDocumentCommand{\DrawCoordinateGrid}{O{} m m m m m m}{%
\def\XGridMin{#2}
\def\XGridMax{#3}
\def\YGridMin{#4}
\def\YGridMax{#5}
\def\ZGridMin{#6}
\def\ZGridMax{#7}
%
\begin{scope}[canvas is xy plane at z=0, ultra thin, gray!75]
\draw [#1] (\XGridMin,\YGridMin) grid (\XGridMax,\YGridMax);
\end{scope}
\begin{scope}[canvas is yz plane at x=0, ultra thin, gray!75]
\draw [#1] (\YGridMin,\ZGridMin) grid (\YGridMax,\ZGridMax);
\end{scope}
\begin{scope}[canvas is xz plane at y=0, ultra thin, gray!75]
\draw [#1] (\XGridMin,\ZGridMin) grid (\XGridMax,\ZGridMax);
\end{scope}
}
\NewDocumentCommand{\DrawCoordinateAxis}{O{} m m m m m m}{%
\def\XAxisMin{#2}
\def\XAxisMax{#3}
\def\YAxisMin{#4}
\def\YAxisMax{#5}
\def\ZAxisMin{#6}
\def\ZAxisMax{#7}
%
\begin{scope}[thin, gray, -latex]
\draw [#1] (\XAxisMin,0,0) -- (\XAxisMax,0,0) node [below left] {$x$};
\draw [#1] (0,\YAxisMin,0) -- (0,\YAxisMax,0) node [right] {$y$};
\draw [#1] (0,0,\ZAxisMin) -- (0,0,\ZAxisMax) node [above] {$z$};
\end{scope}
}%
\newcommand*\Width{2.5}%
\newcommand*\Depth{4.5}%
\newcommand*\Height{2.0}%
\tikzset{Line Style/.style={draw=brown, ultra thick, join=round}}
\begin{document}
\begin{tikzpicture}[
x={(-0.5cm,-0.5cm)},
y={(0.9659cm,-0.25882cm)},
z={(0cm,1cm)}]
\coordinate (O) at (0,0,0);
%% ---------------------------------------------- yz plane at x=0
\coordinate (A) at (0,\Width,0);
\coordinate (B) at (0,\Width,\Height);
\coordinate (C) at (0,0,\Height);
%% ---------------------------------------------- yz plane at x=\Depth
\coordinate (D) at (\Depth,0,0);
\coordinate (E) at (\Depth,\Width,0);
\coordinate (F) at (\Depth,\Width,\Height);
\coordinate (G) at (\Depth,0,\Height);
\DrawCoordinateGrid{0}{6}{0}{4}{0}{3}
\DrawCoordinateAxis[thick, black]{0}{6.5}{0}{4.5}{0}{3.5}
%% ------------------------------------ Draw the rectangular prism
\draw [Line Style] (O) -- (A) -- (B) -- (C) -- cycle;% yz plane at x=0
\draw [Line Style] (D) -- (E) -- (F) -- (G) -- cycle;% yz plane at x=\Depth
\draw [Line Style] (O) -- (D) -- (G) -- (C) -- cycle;% xz plane at y=0
\draw [Line Style] (A) -- (E) -- (F) -- (B) -- cycle;% xz plane at y=\Width
% modification angleshift
\path [angleshift=30, blue, indicate dimensions={$2$}, inner sep=2pt]
(C) -- (G);
%% Following is for debugging purposes so you can see where the points are
%% These are last so that they show up on top
\foreach \xy in {O, A, B, C, D, E, F, G}{
\node at (\xy) {\tiny\xy};
}
\end{tikzpicture}
\end{document}