如何画圆柱体和圆锥体来完成这个绘图?

如何画圆柱体和圆锥体来完成这个绘图?

经过多次尝试均未成功,我在此询问:

  1. 如何绘制连接两个圆的圆柱体?
  2. 如何从点A到最近的圆绘制一个圆锥体?

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{3d}

% define vertical well
\newcommand\well[2]{\draw[very thick] (#1,#2,-1) -- (#1,#2,1)}

% number of wells in arrangement per dimension
\pgfmathsetmacro{\nwells}{6}

\begin{document} 

\begin{tikzpicture}[x = {(0.5cm,0.5cm)},
                    y = {(0.95cm,-0.25cm)},
                    z = {(0cm,0.9cm)}]

% draw odd wells
\foreach \x in {1,3,...,\nwells}{
  \foreach \y in {1,3,...,\nwells}{
    \well{\x}{\y};
  }
}

% draw even wells
\foreach \x in {0,2,...,\nwells}{
  \foreach \y in {0,2,...,\nwells}{
    \well{\x}{\y};
  }
}

% draw some guides
\pgfmathsetmacro{\d}{-0.8}
\draw[stealth-stealth] (\d,0,-1) -- (\d,1,-1) node[below,midway] {$s$};
\draw[dotted] (\d,0,-1) -- (0,0,-1);
\draw[dotted] (\d,1,-1) -- (1,1,-1);

% draw cylinder
\pgfmathsetmacro{\r}{1}
\begin{scope}[canvas is yz plane at x=1]
\filldraw[gray,opacity=.2] (0,0) circle (\r);
\draw[densely dashed,-stealth] (0,0) -- (\r,0) node[above left] {$r$};
\draw (\r,0) arc (0:360:\r);
\end{scope}
\begin{scope}[canvas is yz plane at x=\nwells]
\filldraw[gray,opacity=.2] (0,0) circle (\r);
\draw (\r,0) arc (0:360:\r);
\end{scope}

% coordinates of cone start
\node[left] (1,0,0) {A};

% draw direction
\draw[densely dotted,-stealth] (-1,0,0) -- (\nwells+2,0,0) node[above] {$\vec{h}$};

\end{tikzpicture}

\end{document}

预览

答案1

这是一个建议。圆柱体是自动绘制的,也就是说,绘制近似值并不差。一般策略是找到形状的切线:

  1. 对于圆柱边界,这些是圆的切线。如果圆没有变形,切线就相当明显:只需计算连接圆心的线的斜率,这就会给出一个斜率角,它决定了切线与圆相交的点。只要圆的变形不是太剧烈,这是一个合理的近似值。
  2. 同样,对于圆锥,必须确定穿过 的圆的切线斜率A。不幸的是,tangent cs:似乎在 3d 范围内不起作用,因此必须手动执行。更具体地说,有一个循环,其中 TiAZ 通过最大化或最小化从圆上各点 延伸的线的角度来实现这一点。

对于圆锥体我没有找到近似值,部分原因是您使用的坐标系不是正交的,变换矩阵的行列式是负的。

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{3d,calc}

% define vertical well
\newcommand\well[2]{\draw[very thick] (#1,#2,-1) -- (#1,#2,1)}

% number of wells in arrangement per dimension
\pgfmathsetmacro{\nwells}{6}

\begin{document} 

\begin{tikzpicture}[x = {(0.5cm,0.5cm)},
                    y = {(0.95cm,-0.25cm)},
                    z = {(0cm,0.9cm)}]

% draw odd wells
\foreach \x in {1,3,...,\nwells}{
  \foreach \y in {1,3,...,\nwells}{
    \well{\x}{\y};
  }
}

% draw even wells
\foreach \x in {0,2,...,\nwells}{
  \foreach \y in {0,2,...,\nwells}{
    \well{\x}{\y};
  }
}

% draw some guides
\pgfmathsetmacro{\d}{-0.8}
\draw[stealth-stealth] (\d,0,-1) -- (\d,1,-1) node[below,midway] {$s$};
\draw[dotted] (\d,0,-1) -- (0,0,-1);
\draw[dotted] (\d,1,-1) -- (1,1,-1);

% draw cylinder
\pgfmathsetmacro{\r}{1}
\begin{scope}[canvas is yz plane at x=1]
  \filldraw[gray,opacity=.2] (0,0) coordinate(x1) circle (\r);
  \draw[densely dashed,-stealth] (0,0) -- (\r,0) node[above left] {$r$};
  \draw (\r,0) arc (0:360:\r);
\end{scope}

\coordinate[label=left:A] (A) at (-1,0,0);

\begin{scope}[canvas is yz plane at x=\nwells]
  \filldraw[fill=gray,fill opacity=.2] (0,0) coordinate (x2)  circle (\r);
  \draw (\r,0) arc (0:360:\r);
  \draw[densely dashed,-stealth] (0,0) -- (\r,0) node[above left] {$r$};
  \shade let \p1=($(x1)-(x2)$),\n1={atan2(\y1,\x1)} in 
  [top color=black!80,bottom color=black!70,middle color=gray!20,shading angle=\n1,
  opacity=0.8]
  ($(x1)+(\n1+90:\r)$) -- ($(x2)+(\n1+90:\r)$)
  arc(\n1+90:\n1+270:\r) -- ($(x1)+(\n1-90:\r)$)
  arc(\n1+270:\n1+90:\r);
\end{scope}


\begin{scope}[canvas is yz plane at x=1]
  \xdef\olddim{0pt} 
  \xdef\oldanL{0}   
  \foreach \XX in {90,91,...,270}       
    {\path let \p1=($(\XX:\r)-(A)$),\n1={atan2(\y1,\x1)} in
    \pgfextra{\ifdim\n1>\olddim
    \xdef\olddim{\n1}
    \xdef\oldanL{\XX}
    \fi};}     
  \xdef\olddim{180pt}   
  \xdef\oldanR{0}   
  \foreach \XX in {90,89,...,-90}       
    {\path let \p1=($(\XX:\r)-(A)$),\n1={atan2(\y1,\x1)} in
    \pgfextra{\ifdim\n1<\olddim
    \xdef\olddim{\n1}
    \xdef\oldanR{\XX}
    \fi};}    
  \shade[draw=black] let \p1=($(x1)-(x2)$),
    \n1={atan2(\y1,\x1)} in 
    [top color=black,bottom color=black!80,middle color=gray!20,,shading angle=\n1,
    opacity=0.8] ($(x1)+(\oldanL:\r)$) arc(\oldanL:\oldanR:\r) -- (A) -- cycle;  
\end{scope}
% coordinates of cone start

\foreach \x in {1,3,...,\nwells}{
    \well{\x}{1};
}
\well{0}{0};


% draw direction
\draw[densely dotted,-stealth] (-1,0,0) -- (\nwells+2,0,0) node[above] {$\vec{h}$};

\end{tikzpicture}

\end{document}

在此处输入图片描述

这里有一个替代方案,我切换到tikz-3dplot,它以一种可以说更直接的方式为您提供正交坐标系。缺点是我必须改变一个方向才能使变换的行列式为正。我还将两个循环合并为一个(使用\ifodd)。还请注意,我的代码是一个近似值,只要 中的旋转角度\tdplotsetrotatedcoords{0}{10}{00}不是太大,它就可以工作。可以想象,可以推导出一个精确的公式,但这可能只是意味着重新发明asymptote已经内置的东西。

\documentclass[tikz,border=5pt]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{3d,calc}
% define vertical well
\newcommand\well[2]{\draw[very thick] (#1,#2,-1) -- (#1,#2,1)}

% number of wells in arrangement per dimension
\pgfmathsetmacro{\nwells}{6}

\begin{document} 

\tdplotsetmaincoords{70}{110}
\tdplotsetrotatedcoords{0}{10}{00}
\begin{tikzpicture}[tdplot_rotated_coords]
% these coordinate axes may be helpful when constructing the graph
% \draw[-latex] (0,0,0) -- (4,0,0) node[pos=1.1]{$x$};
% \draw[-latex] (0,0,0) -- (0,4,0) node[pos=1.1]{$y$};
% \draw[-latex] (0,0,0) -- (0,0,4) node[pos=1.1]{$z$};

\foreach \x in {0,1,...,\nwells}{
\ifodd\x
  \foreach \y in {1,3,...,\nwells}{
    \well{\x+1}{\y};
  }
\else
  \foreach \y in {0,2,...,\nwells}{
    \well{\x+1}{\y};
  }
\fi  
}


% draw some guides
\pgfmathsetmacro{\d}{0.8}
\draw[stealth-stealth] (\nwells+\d,0,-1) -- (\nwells+\d,1,-1) node[below,midway] {$s$};
\draw[dotted] (\nwells+\d,0,-1) -- (\nwells,0,-1);
\draw[dotted] (\nwells+\d,1,-1) -- (\nwells-1,1,-1);

% draw cylinder
\pgfmathsetmacro{\r}{1}
\begin{scope}[canvas is yz plane at x=1]
  \filldraw[fill=gray,fill opacity=.2] (0,0) coordinate (x1) circle (\r);
\end{scope}

% coordinates of cone start
\coordinate [label=left:A] (A) at (\nwells+2,0,0);

\begin{scope}[canvas is yz plane at x=\nwells]
  \filldraw[fill=gray,fill opacity=.2] (0,0) coordinate (x2)  circle (\r);
  \draw[densely dashed,-stealth] (0,0) -- (\r,0) node[above left] {$r$};
  \shade let \p1=($(x1)-(x2)$),\n1={atan2(\y1,\x1)} in 
   [top color=black,bottom color=black!80,middle color=gray!20,shading angle=\n1,
    opacity=0.8]
   ($(x1)+(\n1+90:\r)$) -- ($(x2)+(\n1+90:\r)$)
   arc(\n1+90:\n1-90:\r) -- ($(x1)+(\n1-90:\r)$)
   arc(\n1-90:\n1+90:\r);
  \shade[draw=black] let \p1=($(x1)-(x2)$),
    \p2=($(A)-(x1)$),
    \n1={atan2(\y1,\x1)},\n2={veclen(\y2,\x2)},
    \n3={180+atan2(\r*1cm,\n2)} in 
    %\pgfextra{\typeout{\n1,\n2,\n3}}
    [top color=black,bottom color=black!80,middle color=gray!20,,shading angle=\n1,
    opacity=0.8] ($(x2)+(\n3:\r)$) arc(\n3:\n3-270:\r) -- (A) -- cycle;   
\end{scope}

\foreach \x in {1,3,...,\nwells}{
    \well{\x+1}{1};
}

% draw direction
\draw[densely dotted,-stealth] (\nwells+2,0,0) -- (-1,0,0)node[above] {$\vec{h}$};
\end{tikzpicture}
\end{document}

在此处输入图片描述

刚刚意识到可以让 TiZ 搜索切线。这个方法效果出奇地好,让我能够制作出必需的动画。

\documentclass[tikz,border=5pt]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{3d,calc}
% define vertical well
\newcommand\well[2]{\draw[very thick] (#1,#2,-1) -- (#1,#2,1)}

% number of wells in arrangement per dimension
\pgfmathsetmacro{\nwells}{6}

\begin{document} 
\foreach \X in {100,102,...,140,138,...,112}
{\tdplotsetmaincoords{70}{\X}
\tdplotsetrotatedcoords{0}{10}{00}
\begin{tikzpicture}[tdplot_rotated_coords]
% these coordinate axes may be helpful when constructing the graph
% \draw[-latex] (0,0,0) -- (4,0,0) node[pos=1.1]{$x$};
% \draw[-latex] (0,0,0) -- (0,4,0) node[pos=1.1]{$y$};
% \draw[-latex] (0,0,0) -- (0,0,4) node[pos=1.1]{$z$};

\foreach \x in {0,1,...,\nwells}{
\ifodd\x
  \foreach \y in {1,3,...,\nwells}{
    \well{\x+1}{\y};
  }
\else
  \foreach \y in {0,2,...,\nwells}{
    \well{\x+1}{\y};
  }
\fi  
}


% draw some guides
\pgfmathsetmacro{\d}{0.8}
\draw[stealth-stealth] (\nwells+\d,0,-1) -- (\nwells+\d,1,-1) node[below,midway] {$s$};
\draw[dotted] (\nwells+\d,0,-1) -- (\nwells,0,-1);
\draw[dotted] (\nwells+\d,1,-1) -- (\nwells-1,1,-1);

% draw cylinder
\pgfmathsetmacro{\r}{1}
\begin{scope}[canvas is yz plane at x=1]
  \filldraw[fill=gray,fill opacity=.2] (0,0) coordinate (x1) circle (\r);
\end{scope}

% coordinates of cone start
\coordinate [label=left:A] (A) at (\nwells+2,0,0);

\begin{scope}[canvas is yz plane at x=\nwells]
  \filldraw[fill=gray,fill opacity=.2] (0,0) coordinate (x2)  circle (\r);
  \draw[densely dashed,-stealth] (0,0) -- (\r,0) node[above left] {$r$};
  \shade let \p1=($(x1)-(x2)$),\n1={atan2(\y1,\x1)} in 
   [top color=black,bottom color=black!80,middle color=gray!20,shading angle=\n1,
    opacity=0.8]
   ($(x1)+(\n1+90:\r)$) -- ($(x2)+(\n1+90:\r)$)
   arc(\n1+90:\n1-90:\r) -- ($(x1)+(\n1-90:\r)$)
   arc(\n1-90:\n1+90:\r);
  \xdef\olddim{0pt} 
  \xdef\oldanL{0}   
  \foreach \XX in {90,91,...,270}       
    {\path let \p1=($(\XX:\r)-(A)$),\n1={atan2(\y1,\x1)} in
    \pgfextra{\ifdim\n1>\olddim
    \xdef\olddim{\n1}
    \xdef\oldanL{\XX}
    \fi};}     
  \xdef\olddim{180pt}   
  \xdef\oldanR{0}   
  \foreach \XX in {90,89,...,-90}       
    {\path let \p1=($(\XX:\r)-(A)$),\n1={atan2(\y1,\x1)} in
    \pgfextra{\ifdim\n1<\olddim
    \xdef\olddim{\n1}
    \xdef\oldanR{\XX}
    \fi};}    
  \shade[draw=black] let \p1=($(x1)-(x2)$),
    \n1={atan2(\y1,\x1)} in 
    [top color=black,bottom color=black!80,middle color=gray!20,,shading angle=\n1,
    opacity=0.8] ($(x2)+(\oldanL:\r)$) arc(\oldanL:\oldanR:\r) -- (A) -- cycle;  

\end{scope}
\foreach \x in {1,3,...,\nwells}{
    \well{\x+1}{1};
}

% draw direction
\draw[densely dotted,-stealth] (\nwells+2,0,0) -- (-1,0,0)node[above] {$\vec{h}$};
\end{tikzpicture}}
\end{document}

在此处输入图片描述

相关内容