我设法想出了以下具有不同方向的盒子的图片。但现在我想让它们都在同一平面上,我想用某个平面(当前为黑色矩形)来表示。问题是,我怎样才能旋转物体而不改变视角?
蓝色和红色盒子及其内容应该与黄色盒子位于同一平面上,但目前情况并非如此。
我的想法是使用 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
(该组是必需的,因为您还将其用于fill
q_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 轴来解决。