shader
我对 中的曲面图设置感到困惑pgfplots
。具体来说,我想制作一个复数列表相位的二维曲面图。这意味着数据列表中存在不连续性,例如从 π 到 -π,这对于解释和可视化基本上毫无意义。
我已经找到了所谓的循环颜色图,它的两端颜色相同。到目前为止,我最喜欢的是来自 matplotlib 的暮光之城,我已将其转换为pgfplots
使用 Python 脚本在以下 MWE 中,它以非常简化的形式包含。
现在的问题是,用于表面图的美观着色器(即除 之外的任何着色器)shader = flat corner
在非连续性值之间取一些值,以在中间插入值。如果从 π 跳到 -π,颜色会变为黑色,而不是保持白色。不幸的是,flat corner
着色器需要大量的过采样才能接近interp
着色器的外观,因此这不是一个真正可接受的解决方案。
一种解决方案是定期扩展颜色图并使用某种 2D 相位展开算法,但我不得不承认,我目前还不太清楚如何做,因为相位展开似乎并不完全简单。此外,这更像是一种绕过插值着色器限制的方法,而不是令人满意的解决方案。
更好的方法可能是改变着色器的工作方式,以便使用 pgfplots 中的循环颜色图。但我真的不知道该怎么做。也许可以检测极值(更接近元值的最大值/最小值而不是平均元值)并在这种情况下以循环方式更改用于插值的颜色图?
当然,我有一个简短的演示,演示了使用循环色图的不连续性效果。除了从正数到负数的过渡外,插值版本看起来很多更好。
\documentclass{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{colormaps}
\pgfplotsset{compat=newest}
\pgfplotsset{
colormap/twilight/.style={colormap={twilight}{[1pt]
rgb(0pt)=(0.8857501584075443, 0.8500092494306783, 0.8879736506427196);
rgb(25pt)=(0.38407269378943537, 0.46139018782416635, 0.7309466543290268);
rgb(50pt)=(0.18488035509396164, 0.07942573027972388, 0.21307651648984993);
rgb(75pt)=(0.6980608153581771, 0.3382897632604862, 0.3220747885521809);
rgb(100pt)=(0.8857115512284565, 0.8500218611585632, 0.8857253899008712);
}}}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
view={90}{90},
colormap/twilight,
colorbar
]
\addplot3[
mesh/rows=8,
surf,
shader = interp,
] coordinates {
(0,0, 0) (0,1, 0)
(1,0, 1) (1,1, 1)
(2,0, 2) (2,1, 2)
(3,0, 3) (3,1, 3)
(4,0,-3) (4,1,-3)
(5,0,-2) (5,1,-2)
(6,0,-1) (6,1,-1)
(7,0, 0) (7,1, 0)
};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
view={90}{90},
colormap/twilight,
colorbar
]
\addplot3[
mesh/rows=8,
surf,
shader = flat corner,
] coordinates {
(0,0, 0) (0,1, 0)
(1,0, 1) (1,1, 1)
(2,0, 2) (2,1, 2)
(3,0, 3) (3,1, 3)
(4,0,-3) (4,1,-3)
(5,0,-2) (5,1,-2)
(6,0,-1) (6,1,-1)
(7,0, 0) (7,1, 0)
};
\end{axis}
\end{tikzpicture}
\end{document}
答案1
编辑:新的、更好的解决方案
我想到了一个无需绕道的实现colormap access=direct
。这种方式只需要了解出现的point meta min
和 point meta max
值,这对于相位图来说通常很清晰,并且很容易从数据中提取。因此,它更加灵活,不需要额外的数据准备,因为一切都在代码内部完成。
restrict z to domain=-2:2
相位(或循环数据)中的不连续性在两秒内被滤除\addplot
,元值必须根据和设置point meta min=-3.14
,point meta max=3.14
或π的某个更精确的值。第一个图是正常图(在左图下方的图片中),第二个图(下图:中间)使用移位版本的颜色图(适用于黄昏,否则可能必须构建)和根据对数据的简单操作z expr={\thisrow{z} > 0 ? -(\thisrow{z} - 3.14) : -(\thisrow{z} + 3.14) }
。两个图的叠加给出了一个很好的连续和插值曲面图。边界restrict
可能需要根据绘图数据进行调整。
\documentclass{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{colormaps}
\pgfplotsset{compat=newest}
\pgfplotsset{
colormap/twilight/.style={colormap={twilight}{[1pt]
rgb(0pt)=(0.8857501584075443, 0.8500092494306783, 0.8879736506427196);
rgb(25pt)=(0.38407269378943537, 0.46139018782416635, 0.7309466543290268);
rgb(50pt)=(0.18488035509396164, 0.07942573027972388, 0.21307651648984993);
rgb(75pt)=(0.6980608153581771, 0.3382897632604862, 0.3220747885521809);
rgb(100pt)=(0.8857115512284565, 0.8500218611585632, 0.8857253899008712);
}},
colormap/twilight_shifted/.style={colormap={twilight_shifted}{[1pt]
rgb(0pt)=(0.18739228342697645, 0.07710209689958833, 0.21618875376309582);
rgb(25pt)=(0.38407269378943537, 0.46139018782416635, 0.7309466543290268);
rgb(50pt)=(0.8857115512284565, 0.8500218611585632, 0.8857253899008712);
rgb(75pt)=(0.6980608153581771, 0.3382897632604862, 0.3220747885521809);
rgb(100pt)=(0.18488035509396164, 0.07942573027972388, 0.21307651648984993);
}}}
\begin{filecontents}{data.txt}
x y z
0 0 0
0 1 0
1 0 1
1 1 1
2 0 2
2 1 2
3 0 3
3 1 3
4 0 -3
4 1 -3
5 0 -2
5 1 -2
6 0 -1
6 1 -1
7 0 0
7 1 0
\end{filecontents}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
view={90}{90},
colormap/twilight,
colorbar,
title=normal colormap,
]
\addplot3[
mesh/rows=8,
surf,
colormap/twilight,
shader = interp,
point meta min= -3.14,
point meta max= 3.14,
] table[restrict z to domain=-2:2] from {data.txt};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
view={90}{90},
colormap/twilight_shifted,
colorbar,
xmin=0,xmax=7,
title=plus shifted colormap,
]
\addplot3[
mesh/rows=8,
surf,
colormap/twilight_shifted,
shader = interp,
point meta min= -3.14,
point meta max= 3.14,
] table[z expr={\thisrow{z} > 0 ? -(\thisrow{z} - 3.14) : -(\thisrow{z} + 3.14) }, % minus signs are necessary due to 'inverted' definition of twilight_shifted
restrict z to domain=-2:2
] from {data.txt};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
view={90}{90},
colormap/twilight,
colorbar,
title=results in a complete plot,
]
\addplot3[
mesh/rows=8,
surf,
colormap/twilight,
shader = interp,
point meta min= -3.14,
point meta max= 3.14,
] table[restrict z to domain=-2:2] from {data.txt};
\addplot3[
mesh/rows=8,
surf,
colormap/twilight_shifted,
shader = interp,
point meta min= -3.14,
point meta max= 3.14,
] table[z expr={\thisrow{z} > 0 ? -(\thisrow{z} - 3.14) : -(\thisrow{z} + 3.14) }, % minus signs are necessary due to 'inverted' definition of twilight_shifted
restrict z to domain=-2:2
] from {data.txt};
\end{axis}
\end{tikzpicture}
\end{document}
以前的解决方案输出比较丑陋,为了完整性,留在这里
一种方法,可能只适用于相当精细的采样(即,只有当颜色从一个点到另一个点平滑过渡时)是改变 到 的方式colormap access
。direct
然而,这要求meta
(或此处z
)值从颜色图定义的范围中取值。不是很好,但不错的输出证明了手段的合理性 :)
颜色图缩放来自这篇文章被用来为颜色条提供至少正确的刻度(但输入数据必须以缩放形式提供)。
\documentclass{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{colormaps}
\pgfplotsset{compat=newest}
\pgfplotsset{
colormap/twilight/.style={colormap={twilight}{[1pt]
rgb(0pt)=(0.8857501584075443, 0.8500092494306783, 0.8879736506427196);
rgb(25pt)=(0.38407269378943537, 0.46139018782416635, 0.7309466543290268);
rgb(50pt)=(0.18488035509396164, 0.07942573027972388, 0.21307651648984993);
rgb(75pt)=(0.6980608153581771, 0.3382897632604862, 0.3220747885521809);
rgb(100pt)=(0.8857115512284565, 0.8500218611585632, 0.8857253899008712);
}}}
\pgfplotsset{
linear colormap trafo/.code n args={4}{
\def\scalefactor{((#2-#1) / (#4-#3))}%
\def\offsetin{(#3)}%
\def\offsetout{(#1)}%
\pgfkeysalso{%
y coord trafo/.code={%
\pgfmathparse{(##1)}%-\offsetin )*\scalefactor + \offsetout}%
% this part of the transformation does not work
% it seems not to be 'compatible' with colormap access=direct
},
y coord inv trafo/.code={%
\pgfmathparse{(##1-\offsetout)/\scalefactor + \offsetin}%
},
}%
},
colorbar map from to/.code n args={4}{
\def\scalefactor{((#2-#1) * (#4-#3))}%
\def\offsetin{(#1)}%
\def\offsetout{(#3)}%
\pgfkeysalso{
colorbar style={
linear colormap trafo={#1}{#2}{#3}{#4},
point meta min={#1},
point meta max={#2},
},
% point meta={(y)},%-\offsetin )/\scalefactor + \offsetout},
}%
},
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
view={90}{90},
colormap/twilight,
colorbar,
colorbar map from to={0}{100}{-3.14159265359}{3.14159265359},
]
\addplot3[
mesh/rows=8,
surf,
shader = interp, colormap access=direct,
] coordinates {
(0,0, 50) (0,1, 50)
(1,0, 63) (1,1, 63)
(2,0, 76) (2,1, 76)
(3,0,100) (3,1,100)
(4,0, 5) (4,1, 5)
(5,0, 24) (5,1, 24)
(6,0, 37) (6,1, 37)
(7,0, 50) (7,1, 50)
};
\end{axis}
\end{tikzpicture}
\end{document}