经过多次尝试均未成功,我在此询问:
- 如何绘制连接两个圆的圆柱体?
- 如何从点
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
这是一个建议。圆柱体是自动绘制的,也就是说,绘制近似值并不差。一般策略是找到形状的切线:
- 对于圆柱边界,这些是圆的切线。如果圆没有变形,切线就相当明显:只需计算连接圆心的线的斜率,这就会给出一个斜率角,它决定了切线与圆相交的点。只要圆的变形不是太剧烈,这是一个合理的近似值。
- 同样,对于圆锥,必须确定穿过 的圆的切线斜率
A
。不幸的是,tangent cs:
似乎在 3d 范围内不起作用,因此必须手动执行。更具体地说,有一个循环,其中 Ti钾A
Z 通过最大化或最小化从圆上各点 延伸的线的角度来实现这一点。
对于圆锥体我没有找到近似值,部分原因是您使用的坐标系不是正交的,变换矩阵的行列式是负的。
\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}
刚刚意识到可以让 Ti钾Z 搜索切线。这个方法效果出奇地好,让我能够制作出必需的动画。
\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}