如何绘制斜截的圆柱,要求倾斜的椭圆截面与圆柱的母线精确相切?

发布于 2025-07-18 09:32:48

fde60a29402b5546531917771d9103fe.png

使用下面类似的代码,关键的问题在于:斜截椭圆的「长轴端点不好确定」,很难保持其与椭圆的母线相切。

\draw (0,2.3) circle [x radius=1.3199, y radius=0.4,rotate=45];

这里的x radiusy 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}

image.png

查看更多

关注者
2
被浏览
97
2 个回答
Sagittarius Rover
Sagittarius Rover 14小时前
我要成为Typst糕手/(ㄒoㄒ)/~~

Claim:其实这更多的是一个数学问题...

个人探索的另一个更优雅和直观的方式是基于「一些神必的数学」

image.png

而更碰巧的是,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}

image.png

欣赏一下局部细节

image.png

Edit

忽然想到:

要欣赏一下局部细节

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}

image.png

Sagittarius Rover
Sagittarius Rover 15小时前
我要成为Typst糕手/(ㄒoㄒ)/~~

这是一个不太好的解答,但提供了一个倾斜椭圆绘制的轮子...

要想更方便地仅通过椭圆的「长轴端点」和「离心率」来控制「倾斜」的椭圆,我正好在这里有一个类似的封装\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')

纯属气急败坏的无奈之举,局部的微调精细效果也并不够完美。

image.png

image.png

image.png

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览