Tikz:如何在单个平面上旋转 3D 对象?

Tikz:如何在单个平面上旋转 3D 对象?

我设法想出了以下具有不同方向的盒子的图片。但现在我想让它们都在同一平面上,我想用某个平面(当前为黑色矩形)来表示。问题是,我怎样才能旋转物体而不改变视角?

蓝色和红色盒子及其内容应该与黄色盒子位于同一平面上,但目前情况并非如此。

我的想法是使用 tikZ-3dplot 进行旋转,但因此 tikz-3dplot 的坐标系需要与透视图中的坐标系对齐。如何做到这一点?如果可以做到的话。也欢迎其他方法/解决方案。

在此处输入图片描述

\documentclass[tikz,border=1cm]{standalone}
\usetikzlibrary{backgrounds,perspective} % cleaned up

\begin{document}
\begin{tikzpicture}[>=latex,line cap=round,line join=round,scale=2]
\newcommand{\simpleaxes}[6]{% 1-3 position, 4-6 size
\draw[->] (-0.5+#1,#2,#3) -- (#1+#4,#2,#3) node[pos=1.1]{x};
\draw[->] (#1,-0.5+#2,#3) -- (#1,#2+#5,#3) node[pos=1.1]{y};
\draw[->] (#1,#2,-0.5+#3) -- (#1,#2,#3+#6) node[pos=1.1]{z};}
\tikzset{pics/coordsys/.style={
    code = {\tikzset{coordsys/.cd,#1}
        \draw [->,pic actions] (tpp cs:x=0,y=0,z=0) -- (tpp cs:x=1,y=0,z=0)[red] node[pos=1.4]
        {$\pgfkeysvalueof{/tikz/coordsys/x}$};
        \begin{scope}[on background layer]
        \draw [->,pic actions] (tpp cs:x=0,y=0,z=0) -- (tpp cs:x=0,y=1,z=0)[green!60!black] node[pos=1.2]
        {$\pgfkeysvalueof{/tikz/coordsys/y}$};
        \end{scope}
        \draw [->,pic actions] (tpp cs:x=0,y=0,z=0) -- (tpp cs:x=0,y=0,z=1)[blue] node[pos=1.2]
        {$\pgfkeysvalueof{/tikz/coordsys/z}$};
    }
},coordsys/.cd,x/.initial=x,y/.initial=y,z/.initial=z} 

%%%%%% fix euler rotation: Matlab eul2rotm([pi/4,pi/4,pi/4])*eye(3)
\tikzset{pics/coordsysshift/.style={
    code = {\tikzset{coordsysshift/.cd,#1}
        \draw [->,pic actions] (tpp cs:x=0,y=0,z=0) -- (tpp cs:x=0.5,y=0.5,z=-0.7071)[red] node[pos=1.3]
        {$\pgfkeysvalueof{/tikz/coordsysshift/x}$};
        \begin{scope}[on background layer]
        \draw [->,pic actions] (tpp cs:x=0,y=0,z=0) -- (tpp cs:x=-0.1464,y=0.8536,z=0.5)[green!60!black] node[pos=1.2]
        {$\pgfkeysvalueof{/tikz/coordsysshift/y}$};
        \end{scope}
        \draw [->,pic actions] (tpp cs:x=0,y=0,z=0) -- (tpp cs:x=0.8536,y=-0.1464,z=0.5)[blue] node[pos=1.2]
        {$\pgfkeysvalueof{/tikz/coordsysshift/z}$};
    }
},coordsysshift/.cd,x/.initial=x,y/.initial=y,z/.initial=z} 


\tikzset{pics/complicated/.style={code={\tikzset{complicated/.cd,#1}
\begin{scope}
    \draw[\boxframecolor] (tpp cs:x=0,y=0,z=\cubez) %xy plane/top face
     -- ++(tpp cs:x=\cubex,y=0,z=0)
      -- ++(tpp cs:x=0,y=\cubey,z=0)
       -- ++(tpp cs:x=-\cubex,y=0,z=0) -- cycle;
    \draw[\boxframecolor] (tpp cs:x=0,y=0,z=0) %yz plane/left face
     -- ++(tpp cs:x=0,y=0,z=\cubez)
      -- ++(tpp cs:x=0,y=\cubey,z=0)
       -- ++(tpp cs:x=0,y=0,z=-\cubez) -- cycle;
    \draw[\boxframecolor] (tpp cs:x=0,y=0,z=0) %xz plane/front face
     -- ++(tpp cs:x=\cubex,y=0,z=0)
      -- ++(tpp cs:x=0,y=0,z=\cubez)
       -- ++(tpp cs:x=-\cubex,y=0,z=0) -- cycle;
\end{scope}
\begin{scope}[on background layer]
    \fill[\boxfillcolor] (tpp cs:x=0,y=0,z=\cubez) %xy plane
     -- ++(tpp cs:x=\cubex,y=0,z=0)
      -- ++(tpp cs:x=0,y=\cubey,z=0)
       -- ++(tpp cs:x=-\cubex,y=0,z=0) -- cycle;
    \fill[\boxfillcolor] (tpp cs:x=0,y=0,z=0) %yz plane
     -- ++(tpp cs:x=0,y=0,z=\cubez)
      -- ++(tpp cs:x=0,y=\cubey,z=0)
       -- ++(tpp cs:x=0,y=0,z=-\cubez) -- cycle;
    \fill[\boxfillcolor] (tpp cs:x=0,y=0,z=0) %xz plane
     -- ++(tpp cs:x=\cubex,y=0,z=0)
      -- ++(tpp cs:x=0,y=0,z=\cubez)
       -- ++(tpp cs:x=-\cubex,y=0,z=0) -- cycle;
\end{scope}

%%%% define positioning of M,B frames inside box
\pgfmathsetmacro{\dx}{0.5};
\pgfmathsetmacro{\dy}{0.5};
\pgfmathsetmacro{\dz}{0.4};
\coordinate (origin) at (5,3,0);
%\coordinate (M) at (\dx,\cubey-\dy,\dz);
%\coordinate (B) at (\cubex-\dx,\dy,\cubez-\dz);
\coordinate (M) at (\dx,\dy,\dz);
\coordinate (B) at (\cubex-\dx,\cubey-\dy,\cubez-\dz);

\draw (M) pic[thick] {coordsys={x=x_M,y=y_M,z=z_M}};
\node [below right] at (M.south) {\textit{M}};
\draw (B) pic[dotted] {coordsys={x=x_M',y=y_M',z=z_M'}};
\node [above left] at (B.west) {\textit{B}};
\draw (B) pic[thick] {coordsysshift={x=x_{B},y=y_{B},z=z_{B}}};

\draw [->, thick] (M) -- (B) node [midway,fill=\boxfillcolor] {$q_{MB}, r_{MB}$};
}},complicated/.cd,cube x/.store in=\cubex,cube x=8,
cube y/.store in=\cubey,cube y=8,
cube z/.store in=\cubez,cube z=2,
box fill color/.store in=\boxfillcolor,box fill color=yellow!20!,
box frame color/.store in=\boxframecolor,box frame color=gray!20!,}

\begin{scope}[3d view={-80}{15}]
\path (tpp cs:x=0,y=5,z=0) pic{complicated};
\simpleaxes{0}{0}{0}{8}{8}{2};
\draw (tpp cs:x=-10,y=0,z=0) -- (tpp cs:x=10,y=0,z=0) -- (tpp cs:x=10,y=10,z=0) -- (tpp cs:x=-10,y=10,z=0) --cycle;
\end{scope}
\begin{scope}[3d view={-30}{15}]
\path (tpp cs:x=2,y=4,z=0) pic{complicated={box fill color=blue!20}};
\end{scope}
\begin{scope}[3d view={-10}{15}]
\path (tpp cs:x=0,y=-5,z=0) pic{complicated={box fill color=red!20}};
\end{scope}

\end{tikzpicture}
\end{document}

答案1

我认为问题不一定是旋转错了,而是看了由于绘制顺序而导致错误。我尝试使用一些透明度并在背景上绘制公共平面来解决这个问题。这是结果,与你已经实现的结果没有太大区别:

在此处输入图片描述

为了实现这一点,我将方框的绘图放在 中transparency group,并使用fill opacity=0.8(该组是必需的,因为您还将其用于fillq_MB、r_MB 节点)。我还将所有 更改tpp cs:x=..,y=..,z=..为简单,(..,..,..)如果您不使用消失点,这样就可以正常工作。为了获得一个观看投影,我3d view只使用一次。为了旋转盒子,我使用了rotate around z=<angle>。最后,对于您的coordsysshift图片,我使用了三次连续的 45 度旋转,而不是手动提供矢量端点。最终代码:

\documentclass[tikz,border=1cm]{standalone}
\usetikzlibrary{backgrounds,perspective} % cleaned up

\begin{document}
\begin{tikzpicture}[>=latex,line cap=round,line join=round,scale=2]
\newcommand{\simpleaxes}[6]{% 1-3 position, 4-6 size
\draw[->] (-0.5+#1,#2,#3) -- (#1+#4,#2,#3) node[pos=1.1]{x};
\draw[->] (#1,-0.5+#2,#3) -- (#1,#2+#5,#3) node[pos=1.1]{y};
\draw[->] (#1,#2,-0.5+#3) -- (#1,#2,#3+#6) node[pos=1.1]{z};}
\tikzset{pics/coordsys/.style={
    code = {\tikzset{coordsys/.cd,#1}
        \draw [->,pic actions] (0,0,0) -- (1,0,0)[red] node[pos=1.4]
          {$\pgfkeysvalueof{/tikz/coordsys/x}$};
        \draw [->,pic actions] (0,0,0) -- (0,1,0)[green!60!black] node[pos=1.2]
          {$\pgfkeysvalueof{/tikz/coordsys/y}$};
        \draw [->,pic actions] (0,0,0) -- (0,0,1)[blue] node[pos=1.2]
          {$\pgfkeysvalueof{/tikz/coordsys/z}$};
    }
},coordsys/.cd,x/.initial=x,y/.initial=y,z/.initial=z} 

%%%%%% fix euler rotation: Matlab eul2rotm([pi/4,pi/4,pi/4])*eye(3)
\tikzset{pics/coordsysshift/.style={
    code = {\tikzset{coordsysshift/.cd,#1}
      \begin{scope}[rotate around z=45, rotate around y=45, rotate around x=45]
        \draw [->,pic actions] (0,0,0) -- (1,0,0)[red] node[pos=1.3]
          {$\pgfkeysvalueof{/tikz/coordsysshift/x}$};
        \draw [->,pic actions] (0,0,0) -- (0,1,0)[green!60!black] node[pos=1.2]
          {$\pgfkeysvalueof{/tikz/coordsysshift/y}$};
        \draw [->,pic actions] (0,0,0) -- (0,0,1)[blue] node[pos=1.2]
          {$\pgfkeysvalueof{/tikz/coordsysshift/z}$};
      \end{scope}
    }
},coordsysshift/.cd,x/.initial=x,y/.initial=y,z/.initial=z} 


\tikzset{
  pics/complicated/.style={
    code={
      \tikzset{complicated/.cd,#1}
      \begin{scope}[transparency group, fill opacity=0.8]
          \draw[\boxframecolor,fill=\boxfillcolor] (0,0,\cubez) %xy plane/top face
           -- ++(\cubex,0,0)
            -- ++(0,\cubey,0)
             -- ++(-\cubex,0,0) -- cycle;
          \draw[\boxframecolor,fill=\boxfillcolor] (0,0,0) %yz plane/left face
           -- ++(0,0,\cubez)
            -- ++(0,\cubey,0)
             -- ++(0,0,-\cubez) -- cycle;
          \draw[\boxframecolor,fill=\boxfillcolor] (0,0,0) %xz plane/front face
           -- ++(\cubex,0,0)
            -- ++(0,0,\cubez)
             -- ++(-\cubex,0,0) -- cycle;

        %%%% define positioning of M,B frames inside box
        \pgfmathsetmacro{\dx}{0.5};
        \pgfmathsetmacro{\dy}{0.5};
        \pgfmathsetmacro{\dz}{0.4};
        \coordinate (origin) at (5,3,0);
        %\coordinate (M) at (\dx,\cubey-\dy,\dz);
        %\coordinate (B) at (\cubex-\dx,\dy,\cubez-\dz);
        \coordinate (M) at (\dx,\dy,\dz);
        \coordinate (B) at (\cubex-\dx,\cubey-\dy,\cubez-\dz);

        \draw (M) pic[thick] {coordsys={x=x_M,y=y_M,z=z_M}};
        \node [below right] at (M.south) {\textit{M}};
        \draw (B) pic[dotted] {coordsys={x=x_M',y=y_M',z=z_M'}};
        \node [above left] at (B.west) {\textit{B}};
        \draw (B) pic[thick] {coordsysshift={x=x_{B},y=y_{B},z=z_{B}}};

        \draw [->, thick] (M) -- (B) node [midway,fill=\boxfillcolor] {$q_{MB}, r_{MB}$};
      \end{scope}
    }
  },
  complicated/.cd,
    cube x/.store in=\cubex,
    cube x=8,
    cube y/.store in=\cubey,
    cube y=8,
    cube z/.store in=\cubez,
    cube z=2,
    box fill color/.store in=\boxfillcolor,
    box fill color=yellow!25,
    box frame color/.store in=\boxframecolor,
    box frame color=gray!25
}



\begin{scope}[3d view={-80}{15}]
  \draw[fill=gray!10] (-10,0,0) -- (10,0,0) -- (10,10,0) -- (-10,10,0) -- cycle;
  \simpleaxes{0}{0}{0}{8}{8}{2};
  \path (0,5,0) pic{complicated};
  \path[rotate around z=-50] (2,4,0) pic{complicated={box fill color=blue!25}};
  \path[rotate around z=-70] (0,-5,0) pic{complicated={box fill color=red!25}};
\end{scope}

\end{tikzpicture}
\end{document}

现在唯一剩下的问题是\simpleaxes宏的 z 轴部分位于蓝色框的“后面”,但这可以通过先绘制 x 和 y 轴,然后绘制框,最后绘制 z 轴来解决。

相关内容