3D 图形中的尺寸线

3D 图形中的尺寸线

我正在尝试申请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}

相关内容