如何使用 tikz 或 pgfplots 为绿色表面提供第三维度,并赋予其颜色阴影或灯光效果?
问题是绿色表面看起来平坦的就像红色的一样,但我希望它看起来像两个变量的任意实函数的图(在红色域上)。这就是为什么我也不介意 pgfplots。
无论是否透明,看到轴其实并不重要。
我的最新代码在附录 2 中。
附录
考虑下面的图片:
我希望我的绿色表面看起来与后者中的蓝色表面一样。我发现蓝色表面的轮廓线与橙色表面不同(它不是平移后的相同闭合曲线),这有助于渲染“体积”。但改变这一点对我来说不是问题:我想了解如何在我的图片中对绿色表面进行着色,就像第二张图片中的蓝色表面一样。
第二张图片不如我们用 TikZ/PGF 制作的那么好,但我认为蓝色阴影的形状很合适,可以表达曲率的概念。这就是我想要实现的,无论使用什么语法。
附录(2)
以下是我目前所能做的最好的(阴影方法很弱......)。
\documentclass[border=5mm,tikz=true]{standalone}
\usepackage{tikz,pgfplots}
\usetikzlibrary{decorations.shapes}
\begin{document}
\begin{tikzpicture}[scale=1.25]
\draw [dotted, fill=green!15] plot [smooth cycle] %
coordinates {(-1.14,-1)(-0.84, -.18) (-0.04, 0.3) (2.24, 0) %
(4.48, -0.56) (4.48, -1.46) (3.38,-1.84)(0.38, -1.28)};
\draw [dotted, fill=red!15] plot [smooth cycle] %
coordinates {(-1.04, 1.54) (-0.52, 2.66) (1.22, 3.22) %
(4.48, 2.1)(4.44, 1.14) (3.38, 0.98) (0.84, 2.26)};
%\shadedraw [color=red!15, inner color=red!5, outer color=red!15] (1,3) circle (2mm);
\draw [dotted, fill=red!15] plot [smooth cycle] %
coordinates {(-1.04, 1.54) (-0.52, 2.16) (1.22, 2.72) %
(4.48, 2.1)(4.44, 1.14) (3.38, 0.98) (0.84, 2.26)};
\draw[thick,->] (0,0) -- (-2,-1.5) node[below] {$x$};
\draw[thick,->] (0,0) -- (5,0) node[right] {$y$};
\draw[thick,->] (0,0) -- (0,3) node[above] {$z$};
\filldraw (4.2,3.2) node[left] {$z=f(x,y)$};
\draw [dashed] (3.2,-1) -- (3.2,1.1);
\draw [dashed, lightgray] (3.2,1.1) -- (3.2,2.2);
\filldraw (3.2,-1)circle (2pt) node[left] {$\left(x_0,y_0\right)$};
\filldraw (3.2,2.2)circle (2pt) node[left] %
{$\left(x_0,y_0,f\left(x_0,y_0\right)\right)$};
\end{tikzpicture}
\end{document}
我会发布更新,感谢您的任何提示。
答案1
这是一个有点老套的建议。不是很通用,也不是很好,但可以快速而粗暴地完成工作。另一种方法似乎是手动指定表面并计算“阴影”,以便绘制准确。我认为渲染表面 3D 结构的关键图形功能是绘制其网格,这是由着色器在这里完成的。
在这里,我只是用 2D 区域裁剪 3D 图形,以产生“随机”边框的错觉。原始表面取自这里。
\documentclass[border=5mm]{standalone}
\usepackage{pgfplots, filecontents}
\begin{filecontents*}{filename.txt}
0 0 1.36
1 0 1.50
2 0 1.60
3 0 1.69
4 0 1.77
5 0 1.80
6 0 1.76
7 0 1.68
8 0 1.58
9 0 1.41
10 0 1.24
0 1 1.46
1 1 1.60
2 1 1.73
3 1 1.83
4 1 1.92
5 1 1.97
6 1 1.95
7 1 1.86
8 1 1.73
9 1 1.55
10 1 1.37
0 2 1.54
1 2 1.69
2 2 1.84
3 2 1.97
4 2 2.07
5 2 2.12
6 2 2.11
7 2 2.02
8 2 1.87
9 2 1.68
10 2 1.49
0 3 1.56
1 3 1.74
2 3 1.92
3 3 2.07
4 3 2.18
5 3 2.25
6 3 2.24
7 3 2.14
8 3 1.99
9 3 1.80
10 3 1.59
0 4 1.56
1 4 1.74
2 4 1.96
3 4 2.13
4 4 2.25
5 4 2.32
6 4 2.31
7 4 2.22
8 4 2.07
9 4 1.86
10 4 1.63
0 5 1.56
1 5 1.74
2 5 1.95
3 5 2.14
4 5 2.27
5 5 2.34
6 5 2.33
7 5 2.24
8 5 2.09
9 5 1.88
10 5 1.64
0 6 1.52
1 6 1.71
2 6 1.92
3 6 2.09
4 6 2.22
5 6 2.29
6 6 2.28
7 6 2.20
8 6 2.06
9 6 1.87
10 6 1.65
0 7 1.45
1 7 1.66
2 7 1.85
3 7 2.00
4 7 2.11
5 7 2.18
6 7 2.18
7 7 2.11
8 7 1.98
9 7 1.80
10 7 1.61
0 8 1.37
1 8 1.56
2 8 1.73
3 8 1.87
4 8 1.97
5 8 2.04
6 8 2.04
7 8 1.98
8 8 1.87
9 8 1.71
10 8 1.55
0 9 1.29
1 9 1.41
2 9 1.57
3 9 1.72
4 9 1.82
5 9 1.87
6 9 1.87
7 9 1.83
8 9 1.74
9 9 1.62
10 9 1.47
0 10 1.17
1 10 1.25
2 10 1.41
3 10 1.55
4 10 1.65
5 10 1.70
6 10 1.70
7 10 1.66
8 10 1.58
9 10 1.48
10 10 1.34
\end{filecontents*}
\begin{document}
\begin{tikzpicture}
\begin{axis}[view={-20}{20}, grid=both, xmin=0, ymin=0, zmin=0]
\clip[
rounded corners=5,
x=1.1cm,y=.4cm,z=3cm,
yshift=.1cm, xshift=-.7cm
]
(.3,2) -- (0,1) -- (.5,.3) -- (1,.2) -- (2,1.3) -- (3.5,.5) --
(4.5,2) -- (3.5,3) -- (1.5,3.4) -- (1.5,2.5) --
cycle
[yshift=2.7cm]
(.3,2) -- (0,1) -- (.5,.3) -- (1,.2) -- (2,1.3) -- (3.5,.5) --
(4.5,2)
[rounded corners=0]
parabola[parabola height=1.1cm] cycle
;
\addplot3[surf] file {filename.txt};
\addplot3[surf, point meta=explicit] table [z expr=0, meta index=2] {filename.txt};
\end{axis}
\end{tikzpicture}
\end{document}
答案2
一个解决方案是使用pgf-模糊创建一个类似于深度的模糊阴影。此外,你可以将虚线分成两部分,一部分在前面,一部分在后面,颜色较浅,有助于模仿深度效果:
\documentclass[italian,12pt]{article}
\usepackage{amsfonts,amsmath,amssymb}
\usepackage{lmodern}
\usepackage{tikz,pgfplots}
\usetikzlibrary{shadows.blur}
\usetikzlibrary{decorations.shapes}
\begin{document}
\begin{tikzpicture}[scale=1.5]
\draw[thick,->] (0,0) -- (-2,-1.5) node[below] {$x$};% x axis
\draw[thick,->] (0,0) -- (5,-0) node[right] {$y$};% y axis
\draw[thick,->] (0,-0) -- (0,3) node[above] {$z$};% z axis
\draw [dotted, fill=red!15]% red plain surface
plot [smooth cycle]
coordinates {(-1,-1.45) (0,-.95) (2,-.45) (4,-.95) (2,-2.45) (1.5,-2.25) (1,-2.35) %
(0,-1.95)};
\draw [dashed] (3.2,-1) -- (3.2,1.2);% segment
\draw[dotted,fill=green!15,blur shadow={shadow yshift=-7em, shadow opacity=25}]% green surface
plot [smooth cycle]
coordinates {(-1,.75) (0,1.25) (2,1.75) (4,1.25) (2,-.25) (1.5,-.05) (1,-.15) (0,.25)};
\draw [dashed, lightgray] (3.2,0.4) -- (3.2,1.2);% segment
\filldraw (3.2,-1) circle (2pt)% point (x,y,0)
node[left] {$\left(x_0,y_0,0\right)$};
\filldraw (3.2,1.2) circle (2pt)% point (x,y,f)
node[left] {$\left(x_0,y_0,f\left(x_0,y_0\right)\right)$};
\end{tikzpicture}
\end{document}
诀窍当然是
\draw[dotted,fill=green!15,blur shadow={shadow yshift=-7em}]
% and
\draw [dashed, lightgray] (3.2,0.4) -- (3.2,1.2);% segment
答案3
2015 年更新
灵感来自nonlineartransformations
于这个最近的答案,在直边 TikZ 中实现的一个好方法是,当我发布问题时我想到的是,例如以下内容。
\documentclass[border=5mm,tikz]{standalone}
\usetikzlibrary{decorations.shapes}
\usepgfmodule{nonlineartransformations}
\def\fluttertransform{%
\pgfgetlastxy\x\y
\pgfpoint{\x+sin(\y)}{\y+sin(\x)*(30-\x/2)+\x/10}
}
\begin{document}
\begin{tikzpicture}[scale=1.25]
\draw [dotted, fill=green!15] plot [smooth cycle] %
coordinates {(-1.14,-1)(-0.84, -.18) (-0.04, 0.3) (2.24, 0) %
(4.48, -0.56) (4.48, -1.46) (3.38,-1.84)(0.38, -1.28)};
\begin{scope}[yshift=33mm]
\pgftransformnonlinear{\fluttertransform}
\draw [dotted, fill=red!15] plot [smooth cycle] %
coordinates {(-1.14,-1)(-0.84, -.18) (-0.04, 0.3) (2.24, 0) %
(4.48, -0.56) (4.48, -1.46) (3.38,-1.84)(0.38, -1.28)};
% now the same coordinates as above
\end{scope}
\draw[->] (0,0) -- (-2,-1.5) node[below] {$x$};
\draw[->] (0,0) -- (5,0) node[right] {$y$};
\draw (0,0) -- (0,2.05);
\draw[->,gray] (0,2.05) -- (0,2.6) node[above] {$z$};
\filldraw (4.2,3.2) node[left] {$z=f(x,y)$};
\draw [dashed] (3.2,-1) -- (3.2,1.1);
\draw [dashed,gray] (3.2,1.1) -- (3.2,2.2);
\filldraw (3.2,-1)circle (2pt) node[left] {$\left(x_0,y_0\right)$};
\filldraw (3.2,2.2)circle (2pt) node[left] %
{$\left(x_0,y_0,f\left(x_0,y_0\right)\right)$};
\end{tikzpicture}
\end{document}
无论如何,正如@Bordaigorl 接受的答案一样,选择 pgfplots 绝对比这种业余方式更可取。