冒着在一般 TeX 论坛上问另一个 TIKZ 问题的风险 :),我想知道是否有任何简单的方法可以在 TikZ 中绘制像双曲抛物面这样的直纹曲面?我对曲面本身并不挑剔:我只需要一些视觉效果来制作一个看起来不平凡的曲面,而双曲抛物面就是一个很好的例子,因为它有负曲率。我检查了 texample.net 和谷歌,虽然我找到了一个可以做到这一点的 PSTricks 包,但它不适合我使用 pdflatex 和 Beamer 的工作流程。
答案1
PGFplots 可以很好地处理不太复杂的 3D 图。以下是双曲抛物面的示例:
\documentclass{article}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot3 [surf,shader=flat,draw=black] {x^2-y^2};
\end{axis}
\end{tikzpicture}
\end{document}
答案2
使用类beamer
并运行它以xelatex
直接获取 pdf。它显示了 xy 平面中 3D 曲线的 2D 视图。
\documentclass{beamer}
\usetheme{Warsaw}
\usepackage{pst-solides3d}
\begin{document}
\begin{frame}{Title}
\psset{arrowlength=3,arrowinset=0,unit=0.6,
viewpoint=50 30 25 rtp2xyz,Decran=50,lightsrc=viewpoint}
\begin{center}
\begin{pspicture}(-2,-4)(7,8)
\axesIIID[linecolor=gray](0,0,0)(7,7,7)
\psSolid[ngrid=.3 .3,object=grille,base=1.5 6.5 1.5 6.5,
linewidth=0.4pt,linecolor=gray!50,action=draw]%
\psPoint(4,4,4 5 sub 2 exp 4 5 sub 2 exp sub 6 div 5 add){P}
\psPoint(4,4,0){Po}
\pcline[linecolor=red,linestyle=dashed](P)(Po)\Aput{$z=f(x,y)$}
\psSurface[ngrid=.3 .3,fillcolor=green!30,incolor=gray!30,intersectiontype=0,
intersectionplan={
[0 0 1 -6.5]
[0 0 1 -6.1]
[0 0 1 -5.7]
[0 0 1 -5.3]
[0 0 1 -4.9]},intersectioncolor=(bleu),intersectionlinewidth=1,
linewidth=0.4pt,algebraic](1.5,1.5)(6.5,6.5){ ((y-5)^2-(x-5)^2)/6+5 }
\psdot[linecolor=red,dotscale=0.7](P)
\psdot[dotscale=0.7](Po)
\psPoint(1.5,6.5,0){D}\uput[90](D){$D$}
\psPoint(2,6.5,6.5 5 sub 2 exp 2 5 sub 2 exp sub 6 div 5 add){S}\uput[0](S){$S$}
%% Contouring on xy plane for z=6.5 6.1 5.7 5.3 4.9
%% Explicit representation: z=((y-5)2-(x-5)2)/6+5
%% Parametric representation of z=f(x,y)
%% x=x(x)=x
%% y=y(x)=sqrt((x-5)^2+6*(z-5))+5
%% z=z(x)=0
\psset{object=courbe,r=0,linecolor=blue,resolution=360,function=Fxy,algebraic}
\defFunction{Fxy}(x){x}{-sqrt((x-5)^2+6*(6.5-5))+5}{0}
\psSolid[range=3.155 6.5]
\defFunction{Fxy}(x){x}{-sqrt((x-5)^2+6*(6.1-5))+5}{0}
\psSolid[range=2.6 6.5]
\defFunction{Fxy}(x){x}{-sqrt((x-5)^2+6*(5.7-5))+5}{0}
\psSolid[range=2.15 6.5]
\defFunction{Fxy}(x){x}{-sqrt((x-5)^2+6*(5.3-5))+5}{0}
\psSolid[range=1.75 6.5]
\defFunction{Fxy}(x){x}{sqrt((x-5)^2+6*(5.3-5))+5}{0}
\psSolid[range=4.35 5.7]
\defFunction{Fxy}(x){-sqrt((x-5)^2+6*(5-4.9))+5}{x}{0}
\psSolid[range=1.6 6.5]
\defFunction{Fxy}(x){sqrt((x-5)^2+6*(5-4.9))+5}{x}{0}
\psSolid[range=3.7 6.3]
\end{pspicture}
\end{center}
\end{frame}
\end{document}
答案3
只是因为它很有趣(我并不声称这是绘制它的好方法),利用了表面被划线的事实):
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\definecolor{startcolor}{named}{red}
\definecolor{endcolor}{named}{blue}
\newcommand\steps{250}
\newcommand\lineAstart{0,0,0}
\newcommand\lineAend{1,0,1}
\newcommand\lineBstart{0,1,1}
\newcommand\lineBend{1,1,0}
\begin{tikzpicture}[x={(-3.5cm,-2cm)},y={(10cm,-1cm)},z={(0,7cm)}]
\draw[->] (0,0) -- (1,0,0);
\draw[->] (0,0) -- (0,1,0);
\draw[->] (0,0) -- (0,0,1);
\foreach \n in {0,1,...,\steps} {
\pgfmathparse{\n/\steps*100}
\let\i\pgfmathresult
\draw[ultra thick,color={startcolor!\i!endcolor}]
($(\lineAstart)!{\n/\steps}!(\lineAend)$) --
($(\lineBstart)!{\n/\steps}!(\lineBend)$);
}
\end{tikzpicture}
\end{document}
更有趣的是,我们可以画出两类线:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,intersections}
\begin{document}
\tikzset{f1/.style={red}}
\tikzset{f2/.style={blue}}
\newcommand\steps{40}
\begin{tikzpicture}[x={(-3.5cm,-2cm)},y={(10cm,-1cm)},z={(0,7cm)}]
\coordinate (lineAstart) at (1,0,1);
\coordinate (lineAend) at (0,0,0);
\coordinate (lineBstart) at (1,1,0);
\coordinate (lineBend) at (0,1,1);
\draw[->] (0,0) -- (1,0,0);
\draw[->] (0,0) -- (0,1,0);
\draw[->] (0,0) -- (0,0,1);
%
% Draw the first family of lines
%
\draw[name path global={f1l0},name path global={f1l0-short},f1] (lineAstart) -- (lineBstart);
\foreach \n in {1,...,\steps} {
\pgfmathparse{\n/\steps*100}
\let\i\pgfmathresult
\pgfmathtruncatemacro\p{\n-1}
% Create the path of the lines
\edef\optname{name path global={f1l\n}}
\expandafter\path\expandafter[\optname]
($(lineAstart)!{\n/\steps}!(lineAend)$) --
($(lineBstart)!{\n/\steps}!(lineBend)$);
% Draw the correct bits of the lines
\edef\optname{name intersections={of={f1l\n} and f1l\p},name path global={f1l\n-short}}
\expandafter\draw\expandafter[\optname,f1]
(intersection-1) -- ($(lineBstart)!{\n/\steps}!(lineBend)$);
\edef\optname{name intersections={of={f1l\n} and f1l0}}
\expandafter\draw\expandafter[\optname,f1]
($(lineAstart)!{\n/\steps}!(lineAend)$) -- (intersection-1);
}
%
% Draw the second family of lines
%
\foreach \n in {\steps,...,0} {
\pgfmathparse{\n/\steps*100}
\let\i\pgfmathresult
\pgfmathtruncatemacro\p{\n+1}
% Create the paths
\edef\optname{name path global={f2l\n}}
\expandafter\path\expandafter[\optname,shorten <=4pt]
($(lineAstart)!{\n/\steps}!(lineBstart)$) --
($(lineAend)!{\n/\steps}!(lineBend)$);
% Draw the correct bits
\ifnum\n=\steps % handle the first line separately
\draw[f2] (lineBstart) -- (lineBend);
\else
% Note: one should actually find the intersection with the correct line of the first family.
% However, this is rather complicated. The following gives a good approximation when the
% number of lines is high enough.
\edef\optname{name intersections={of={f2l\n} and f2l\p,total=\noexpand\total}}
\expandafter\draw\expandafter[\optname,f2]
\ifnum\total=1
($(lineAstart)!{\n/\steps}!(lineBstart)$) -- (intersection-1);
\else
($(lineAstart)!{\n/\steps}!(lineBstart)$) -- ($(lineAend)!{\n/\steps}!(lineBend)$);
\fi;
\fi
}
\end{tikzpicture}
或者结合图片: