三维空间中围绕 2 个点的透视平面椭圆

三维空间中围绕 2 个点的透视平面椭圆

我有以下轨迹,它应该描绘刚体上 2 个点的某条路径。每个点都由一个坐标系来表示。现在我想在点周围使用椭圆而不是长方体。这样点出现在椭圆/主体内部。这个椭圆应该只是表示身体的位置和方向,并且应该位于与立方体当前相同的平面上(下方 xy 平面)。

目前我对长方体不满意,因为例如最右边立方体的顶面显示不正确(中间立方体也是如此)。此外,长方体位于框架顶部,而我希望框架位于内部。

我认为需要为顶部轨迹找到不同的参数化,因为顶部轨迹与底部轨迹之间的距离应为固定距离(小于立方体长度),并且其运动不是随机的,而是由物体的距离和角度决定的。此外,两个点都固定在物体上,并经历相同的运动,但顶部框架应相对于底部框架具有固定的相对旋转

我认为省略号更简单,但我对这两种方式都很满意。谢谢!


@Schrödinger 的猫: 请提供一些见解/解释,说明如何获得旋转并参数化点 P 和 Q。此外,P\Y 和 Q\Y 是什么?谢谢!

在此处输入图片描述

\documentclass[border=2mm,tikz]{standalone} 
\usepackage{tikz-3dplot} 
\usetikzlibrary{backgrounds}
\begin{document} 
\tdplotsetmaincoords{60}{-15} 
\begin{tikzpicture}[tdplot_main_coords,scale=1.5,line join=round,>=latex, 
line cap=round,declare function={fA(\t)=-sin(\t*144/(1+\t/5));
fAprime(\t)=pow(60/(5+\t),2)*cos(\t*144/(1+\t/5))*pi/180;
fB(\t)=-sin(\t*216/(1+\t*4/15));
fBprime(\t)=6*pow(90/(15+\t*4),2)*cos(\t*216/(1+\t*4/15))*pi/180;},
pics/coordsys/.style = {
    code = {\tikzset{coordsys/.cd,#1}
        \draw [->,pic actions] (0,0,0) -- +(1,0,0)[red] node[pos=1.1]
        {$\pgfkeysvalueof{/tikz/coordsys/x}$};
        \begin{scope}[on background layer]
        \draw [->,pic actions] (0,0,0) -- +(0,1,0)[green!60!black] node[pos=1.1]
        {$\pgfkeysvalueof{/tikz/coordsys/y}$};
        \end{scope}
        \draw [->,pic actions] (0,0,0) -- +(0,0,1)[blue] node[pos=1.1]
        {$\pgfkeysvalueof{/tikz/coordsys/z}$};
    }
},coordsys/.cd,x/.initial=x,y/.initial=y,z/.initial=z] 
 \draw[dashed] plot[variable=\t,domain=0:5] ({\t},3,{fA(\t)});
 \draw[dashed] plot[variable=\t,domain=0:3.25] ({\t},0,{fB(\t)});
 \foreach \X [count=\Y] in {1,...,3}
 {\draw ({\X*5/3},3,{fA(\X*5/3)}) coordinate (P\Y)
  -- ({\X*3.25/3},0,{fB(\X*3.25/3)}) coordinate (Q\Y);
 \tdplotsetrotatedcoords{0}{atan2(fBprime(\X*3.25/3),1)}{0} 
 \begin{scope}[tdplot_rotated_coords]
 \path (Q\Y) pic{coordsys};
 \pgfmathsetmacro{\myang}{atan2(fBprime(\X*3.25/3),1))}
 \pgfmathtruncatemacro{\itest}{sign(\myang)}
 \pgfmathsetmacro{\cuboiddimx}{2/3}% 2/3 = 1/scale where scale=1.5
 \pgfmathsetmacro{\cuboiddimz}{1/3}% 2/3 = 1/scale where scale=1.5
 \draw[fill opacity=0.5,fill=gray!70]  ($(Q\Y)+(0,0,0)$) 
  --  ($(Q\Y)+(\cuboiddimx,0,0)$) --  ($(Q\Y)+(\cuboiddimx,0,\cuboiddimz)$) 
  -- ($(Q\Y)+(0,0,\cuboiddimz)$) -- cycle;
 \ifnum\itest=-1
 \draw[fill opacity=0.5,fill=gray]  ($(Q\Y)+(\cuboiddimx,0,0)$) 
  --  ($(Q\Y)+(\cuboiddimx,0,\cuboiddimz)$) --  ($(P\Y)+(\cuboiddimx,0,\cuboiddimz)$) 
  -- ($(P\Y)+(\cuboiddimx,0,0)$) -- cycle;
 \else
 \draw[fill opacity=0.5,fill=gray]  ($(Q\Y)+(0,0,0)$) 
  --  ($(Q\Y)+(0,0,\cuboiddimz)$) --  ($(P\Y)+(0,0,\cuboiddimz)$) 
  -- ($(P\Y)+(0,0,0)$) -- cycle;
 \fi 
 \draw[fill opacity=0.5,fill=gray!70]  ($(Q\Y)+(0,0,\cuboiddimz)$) 
  --  ($(Q\Y)+(\cuboiddimx,0,\cuboiddimz)$) --  ($(P\Y)+(\cuboiddimx,0,\cuboiddimz)$) 
  -- ($(P\Y)+(0,0,\cuboiddimz)$) -- cycle;
 \draw[fill opacity=0.5,fill=gray!50]  ($(P\Y)+(0,0,0)$) 
  --  ($(P\Y)+(\cuboiddimx,0,0)$) --  ($(P\Y)+(\cuboiddimx,0,\cuboiddimz)$) 
  -- ($(P\Y)+(0,0,\cuboiddimz)$) -- cycle;

 \end{scope}
 \tdplotsetrotatedcoords{0}{atan2(fAprime(\X*1.25),1)}{0} 
 \begin{scope}[tdplot_rotated_coords]
 \path (P\Y) pic{coordsys={x=x',y=y',z=z'}};
 \end{scope}
 } 
\end{tikzpicture} 
\end{document}

答案1

问题是 TiZ 没有 3D 引擎,因此您需要自己进行 3D 排序。什么是 3D 排序?如果您有两个元素 A 和 B,并且您在 B 之后绘制 A,则 A 将显示在 B 之前。也就是说,您需要稍后绘制更近的物体。哪个更近通常取决于视角,您可以使用 设置视角。如果我没记错的话,与原始代码相比,您已经交换了代码中和\tdplotsetmaincoords{60}{-15}的角色。但是,您并没有改变绘制事物的顺序,因此看起来是错误的。特别是,平面的绘制顺序不正确。我相应地调整了绘制顺序,并在后面添加了一些平面。我还调整了坐标系的绘制顺序。PQxz

\documentclass[border=2mm,tikz]{standalone} 
\usepackage{tikz-3dplot} 
\usetikzlibrary{backgrounds}
\begin{document} 
\tdplotsetmaincoords{60}{-15} 
\begin{tikzpicture}[tdplot_main_coords,scale=1.5,line join=round,>=latex, 
line cap=round,declare function={fA(\t)=-sin(\t*144/(1+\t/5));
fAprime(\t)=pow(60/(5+\t),2)*cos(\t*144/(1+\t/5))*pi/180;
fB(\t)=-sin(\t*216/(1+\t*4/15));
fBprime(\t)=6*pow(90/(15+\t*4),2)*cos(\t*216/(1+\t*4/15))*pi/180;},
pics/coordsys/.style = {
    code = {\tikzset{coordsys/.cd,#1}
        \draw [->,pic actions] (0,0,0) -- +(1,0,0)[red] node[pos=1.1]
        {$\pgfkeysvalueof{/tikz/coordsys/x}$};
        \begin{scope}[on background layer]
        \draw [->,pic actions] (0,0,0) -- +(0,1,0)[green!60!black] node[pos=1.1]
        {$\pgfkeysvalueof{/tikz/coordsys/y}$};
        \end{scope}
        \draw [->,pic actions] (0,0,0) -- +(0,0,1)[blue] node[pos=1.1]
        {$\pgfkeysvalueof{/tikz/coordsys/z}$};
    }
},coordsys/.cd,x/.initial=x,y/.initial=y,z/.initial=z] 
 \draw[dashed] plot[variable=\t,domain=0:5] ({\t},3,{fA(\t)});
 \draw[dashed] plot[variable=\t,domain=0:3.25] ({\t},0,{fB(\t)});
 \foreach \X [count=\Y] in {1,...,3}
 {\draw ({\X*5/3},3,{fA(\X*5/3)}) coordinate (P\Y)
  -- ({\X*3.25/3},0,{fB(\X*3.25/3)}) coordinate (Q\Y);
 \tdplotsetrotatedcoords{0}{atan2(fAprime(\X*5/3),1)}{0} 
 \begin{scope}[tdplot_rotated_coords]
 \path (P\Y) pic{coordsys={x=x',y=y',z=z'}};
 \pgfmathsetmacro{\cuboiddimx}{2/3}% 2/3 = 1/scale where scale=1.5
 \pgfmathsetmacro{\cuboiddimz}{1/3}% 2/3 = 1/scale where scale=1.5
 \pgfmathsetmacro{\myopa}{0.6}
 % xz face at y=3 (back of the cuboid)
 \draw[fill opacity=\myopa,fill=gray!50]  ($(P\Y)+(0,0,0)$) 
  --  ($(P\Y)+(\cuboiddimx,0,0)$) --  ($(P\Y)+(\cuboiddimx,0,\cuboiddimz)$) 
  -- ($(P\Y)+(0,0,\cuboiddimz)$) -- cycle;
 % xy face at bottom
 \draw[fill opacity=\myopa,fill=gray!70]  ($(Q\Y)+(0,0,0)$) 
  --  ($(Q\Y)+(\cuboiddimx,0,0)$) --  ($(P\Y)+(\cuboiddimx,0,0)$) 
  -- ($(P\Y)+(0,0,0)$) -- cycle;
 % in order to find out which yz face is to be drawn first,
 % we need to look at an appropriate rotation angle
 \pgfmathsetmacro{\myang}{atan2(fBprime(\X*3.25/3),1))}
 % the sign of the angle determines the ordering
 \pgfmathtruncatemacro{\itest}{sign(\myang)}
 \ifnum\itest=-1
 % the "left" yz face is "hidden"
 \draw[fill opacity=\myopa,fill=gray]  ($(Q\Y)+(0,0,0)$) 
  --  ($(Q\Y)+(0,0,\cuboiddimz)$) --  ($(P\Y)+(0,0,\cuboiddimz)$) 
  -- ($(P\Y)+(0,0,0)$) -- cycle;
 % the "right" yz face is "visible"
 \draw[fill opacity=\myopa,fill=gray]  ($(Q\Y)+(\cuboiddimx,0,0)$) 
  --  ($(Q\Y)+(\cuboiddimx,0,\cuboiddimz)$) --  ($(P\Y)+(\cuboiddimx,0,\cuboiddimz)$) 
  -- ($(P\Y)+(\cuboiddimx,0,0)$) -- cycle;
 \else
 % the "right" yz face is "hidden"
 \draw[fill opacity=\myopa,fill=gray]  ($(Q\Y)+(\cuboiddimx,0,0)$) 
  --  ($(Q\Y)+(\cuboiddimx,0,\cuboiddimz)$) --  ($(P\Y)+(\cuboiddimx,0,\cuboiddimz)$) 
  -- ($(P\Y)+(\cuboiddimx,0,0)$) -- cycle;
 % the "left" yz face is "visible"
 \draw[fill opacity=\myopa,fill=gray]  ($(Q\Y)+(0,0,0)$) 
  --  ($(Q\Y)+(0,0,\cuboiddimz)$) --  ($(P\Y)+(0,0,\cuboiddimz)$) 
  -- ($(P\Y)+(0,0,0)$) -- cycle;
 \fi 
 % top xy face
 \draw[fill opacity=\myopa,fill=gray!70]  ($(Q\Y)+(0,0,\cuboiddimz)$) 
  --  ($(Q\Y)+(\cuboiddimx,0,\cuboiddimz)$) --  ($(P\Y)+(\cuboiddimx,0,\cuboiddimz)$) 
  -- ($(P\Y)+(0,0,\cuboiddimz)$) -- cycle;
 % front xz face
 \draw[fill opacity=\myopa,fill=gray!70]  ($(Q\Y)+(0,0,0)$) 
  --  ($(Q\Y)+(\cuboiddimx,0,0)$) --  ($(Q\Y)+(\cuboiddimx,0,\cuboiddimz)$) 
  -- ($(Q\Y)+(0,0,\cuboiddimz)$) -- cycle;
 \end{scope}
 \tdplotsetrotatedcoords{0}{atan2(fBprime(\X*3.25/3),1)}{0} 
 \begin{scope}[tdplot_rotated_coords]
 \path (Q\Y) pic{coordsys};
 \end{scope}
 } 
\end{tikzpicture} 
\end{document}

在此处输入图片描述

为了进行交叉检查,我们设置\pgfmathsetmacro{\myopa}{1}

在此处输入图片描述

如果你不想自己进行 3D 排序,你可以考虑半自动解决方案,例如这个或完全切换到asymptote

相关内容