使用下面类似的代码,关键的问题在于:斜截椭圆的「长轴端点不好确定」,很难保持其与椭圆的母线相切。
\draw (0,2.3) circle [x radius=1.3199, y radius=0.4,rotate=45];
这里的x radius
和y radius
怎么调都调不好...
完整代码如下:
\documentclass[tikz,border=5pt]{standalone}
\begin{document}
\begin{tikzpicture}
% 圆柱参数
\def\radius{1}
\def\height{4}
\draw[dashed] (1,0) arc (0:180: 1 and {1/3});
\draw (-1,0) arc (180:360: 1 and {1/3});
\draw (\radius,0) -- (\radius,3.1); % 右侧直线
\draw (-\radius,0) -- (-\radius,1.5); % 左侧直线
\draw (0,2.3) circle [x radius=1.3199, y radius=0.4,rotate=45];
\end{tikzpicture}
\end{document}
个人探索的另一个更优雅和直观的方式是基于「一些神必的数学」
而更碰巧的是,tikz
提供了「coordinate transformation matrix」这样的feature
所以可以得到如下个人觉得比较简单的实现:
\documentclass[tikz,border=5pt]{standalone}
\begin{document}
\def\radius{1}
\def\height{1.05}%to tune the eccentricity
\def\leftheight{2}
\def\rightheight{4}
\def\midheight{\fpeval{(\leftheight+\rightheight)/2}}
\def\hh{\fpeval{abs(\leftheight-\rightheight)/2}}
\begin{tikzpicture}[line join=round]
\draw[dashed] (\radius,0) arc (0:180:{\radius} and {1/3});
\draw (-\radius,0) arc (180:360:{\radius} and {1/3});
\draw (-\radius,0) -- (-\radius,\leftheight) coordinate (A);
\draw (\radius,0) -- (\radius,\rightheight) coordinate (B);
\def\phii{\fpeval{acos(\hh/\height)}}
\def\xa{0}
\def\ya{\fpeval{-\height*sin(\phii)}}
\def\xb{\radius}
\def\yb{\fpeval{\height*cos(\phii)}}
\draw[cm={\xa,\ya,\xb,\yb,(0,\midheight)}] circle [radius=1cm];
\filldraw[red] (A) circle[radius=.5pt] node[left,text=black] {$A$}
(B) circle[radius=.5pt] node[right,text=black] {$B$};
\node[align=left,rectangle] at (\radius+4,\rightheight/2) {%
$\phi$ \texttt{=\phii}\\
$(x_1,y_1)$ \texttt{=(\xa,\ya)}\\
$(x_2,y_2)$ \texttt{=(\xb,\yb)}
};
\end{tikzpicture}
\end{document}
忽然想到:
要欣赏一下局部细节
tikz
提供了spy
这样的工具,尝尝鲜嘻嘻
\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{spy}
\begin{document}
\def\radius{1}
\def\height{1.05}%to tune the eccentricity
\def\leftheight{2}
\def\rightheight{4}
\def\midheight{\fpeval{(\leftheight+\rightheight)/2}}
\def\hh{\fpeval{abs(\leftheight-\rightheight)/2}}
\begin{tikzpicture}[
line join=round,
line cap=round,
spy using outlines={%
circle,size=2cm,
magnification=10,
connect spies
}%
]
\draw[dashed] (\radius,0) arc (0:180:{\radius} and {1/3});
\draw (-\radius,0) arc (180:360:{\radius} and {1/3});
\draw (-\radius,0) -- (-\radius,\leftheight) coordinate (A);
\draw (\radius,0) -- (\radius,\rightheight) coordinate (B);
\def\phii{\fpeval{acos(\hh/\height)}}
\def\xa{0}
\def\ya{\fpeval{-\height*sin(\phii)}}
\def\xb{\radius}
\def\yb{\fpeval{\height*cos(\phii)}}
\draw[cm={\xa,\ya,\xb,\yb,(0,\midheight)}] circle [radius=1cm];
\node[align=left,rectangle] at (\radius+4,1) {%
$\phi$ \texttt{=\phii}\\
$(x_1,y_1)$ \texttt{=(\xa,\ya)}\\
$(x_2,y_2)$ \texttt{=(\xb,\yb)}
};
\spy[red] on (A) in node [left] at (-1,4);
\spy[blue] on (B) in node [right] at (2.5,3);
\end{tikzpicture}
\end{document}
要想更方便地仅通过椭圆的「长轴端点」和「离心率」来控制「倾斜」的椭圆,我正好在这里有一个类似的封装为\mydrawellipse
:
稍微调整了一下:
\documentclass[tikz,border=2pt]{standalone}
\usepackage{tkz-euclide}
\NewDocumentCommand{\mydrawellipse}{O{}O{}mmm}{%
% #3=pointA; #4=pointB; #5=ratio of y on x
\tkzCalcLength(#3,#4)%
\tkzGetLength{tmpdistance}%
\tkzFindSlopeAngle(#3,#4) %
\tkzGetAngle{tmpangle}%
\begin{scope}[rotate=\tmpangle]
\draw[densely dashed,#1] (#4) arc [start angle=0,delta angle=180,
x radius=\fpeval{\tmpdistance/2} cm,y radius=\fpeval
{\tmpdistance * (#5) / 2}cm] (#3);
\draw[#2] (#3) arc[start angle=180,delta angle=180,x
radius=\fpeval{\tmpdistance/2} cm,y radius=\fpeval{\tmpdistance
* (#5) / 2}cm] (#4);
\end{scope}
}
\begin{document}
\begin{tikzpicture}[line join=round]
\def\radius{1}
\def\height{4}
\def\leftheight{1.5}
\def\rightheight{3}
\tkzDefPoint(-\radius,0){A}
\tkzDefPoint(\radius,0){B}
\tkzDefPoint(-\radius,\leftheight){C}
\tkzDefPoint(\radius,\rightheight){D}
\mydrawellipse{A}{B}{.2}
\mydrawellipse[solid]{C}{D}{.18}
\def\myshifta{.004}
\def\myshiftb{.003}
\tkzDefPoint(-\radius-\myshifta,0){A'}
\tkzDefPoint(\radius+\myshiftb,0){B'}
\tkzDefPoint(-\radius-\myshifta,\leftheight){C'}
\tkzDefPoint(\radius+\myshiftb+.003,\rightheight-.01){D'}
\tkzDrawSegments[line width=.4pt](A',C' B',D')
\end{tikzpicture}
\end{document}
但是,由于数学上的原因,「直接以母线上的点作为长轴顶点」的话,椭圆与圆柱的母线必不是相切的。OP提到的「这里的x radius
和 radius
怎么调都调不好...」正是由于此,客观来看,上面代码中的
\def\myshifta{.004}
\def\myshiftb{.003}
\tkzDefPoint(-\radius-\myshifta,0){A'}
\tkzDefPoint(\radius+\myshiftb,0){B'}
\tkzDefPoint(-\radius-\myshifta,\leftheight){C'}
\tkzDefPoint(\radius+\myshiftb+.003,\rightheight-.01){D'}
\tkzDrawSegments[line width=.4pt](A',C' B',D')
纯属气急败坏的无奈之举,局部的微调精细效果也并不够完美。