MATLAB:在曲面图上绘图

MATLAB: Drawing atop a surface plot

我在 MATLAB 中将 R^2 到 R 函数绘制为曲面图,我对其进行了颜色映射并从上方查看。

surf(X, Y, data);
colormap(jet);
colobar;
view(2);

它产生(带有一些额外的代码)类似于

尽管从以下角度更好地观察函数的真实性质(为了理解这个问题):

我想在我原来的图上画一个圆(从上面看)。像...

但是我似乎无法实现这一点,因为在图上绘制平面内元素会使它们出现在 x-y 轴上,而 x-y 轴被我的曲面图覆盖。例如调用

circle_pos = [ +1 +1; -1 -1; -1 +1; +1 -1;]
circle_rad = 0.2 * ones(4,1);
viscircles(circle_pos, circle_rad);

在我的表面图之后,从顶部看时没有可见的圆圈。缩放和旋转显示这些圆圈绘制在 x-y 平面上,因此从上方看不到。

如何在曲面图的顶部绘制我的圆圈,以便从上方可以看到它们? 在表面上绘制 text 时会出现类似的问题,但可以通过在基础函数 z 值上方指定 z 位置值来解决。似乎没有任何方法可以指定这些图形元素的 z 位置。

几个选项spring要考虑。

最简单的方法是使用 plot3:

在 3d 中绘制标记
figure;
peaks;
shading interp;
hold;
x = 0; y = 2; z = 10;
plot3(x, y, z, 'ro', 'MarkerSize', 24);

这可行,但圆圈似乎始终面向观看者:

或者,您可以在 3d 中绘制一个圆:

vfTheta = linspace(0, 2*pi, 300);
figure; peaks; shading interp; hold;
x = 0; y = 2; z = 10; r = 0.2;
plot3(x + r.*cos(vfTheta), y + r.*sin(vfTheta), z .* ones(size(vfTheta)), 'r-', 'LineWidth', 2);

结果:一个漂亮的 3d 光环!

可能没有 直接 方法来指定由 viscircles 编辑的 return 对象的 z 位置,但一般来说之后(大多数情况下)有一种方法可以修改任何图形对象的属性和位置。


方法一:创建后修改圈子。

如果您打算修改图形对象,首先要做的总是检索它的 handle。因此,在您的情况下,您必须通过指定 return 值(它将包含您想要的 handle)来调用 viscircles。:

hg = viscircles(circle_pos, circle_rad);

我没有 Image Processing Toolbox,所以我无权使用 viscircles 功能。但是我从文档中读到句柄 returned 是一个 hggrouphggroup 只是一个包含一个或多个 handles 更原始图形对象的容器。在这种情况下,hggroup 包含 4 个 lines(您的 4 个圆圈)的句柄。

转换 hggroup 中所有对象的最简单方法是使用 hgtransform 对象。我们将定义一个 Translation 转换,hgtransform 将把它应用到 4 个圆(hggroup).

要定义翻译,我们将使用 makehgtform 对象。

我们开始:

ht = hgtransform ;      % create the transform object
set(hg,'Parent',ht) ;   % make it a "parent" of the hggroup

zc = max(max(Z)) ;  % Find by how much we want to translate the circles on the Z axis
Tz = makehgtform('translate',[0 0 zc]) ;   % create the TRANSLATION transform

set(ht,'Matrix',Tz)     % apply the transformation (translation) to the hggroup/hgtransform

大功告成,你的 4 个圆圈现在应该在你的表面上了。请注意,您可以为 zc 指定任何其他值(不仅是曲面的最大值)。


方法二:DIY

如果您不想依赖图像处理工具箱,或者如果您根本没有它,您可以自己在 3D 中创建圆 space 相对容易。

这是一个创建圆的函数,其创建方式与 viscircles 相当,但它还允许您为圆心位置指定一个可选的 z 坐标。

代码 circles_3D.m:

function hg = circles_3d( pos , rad , varargin )

% get current axes handle and hold state
ax = gca ;
holdState = get(ax,'NextPlot') ;    % save state to reinstate after function
set(ax,'NextPlot','add') ;          % equivalent of "hold off"

tt = linspace(0,2*pi) ;
hg = hggroup(ax) ;
for k = 1:numel(rad)

    c = pos(k,:) ;
    r = rad(k) ;
    x = c(1) + r.*cos(tt) ;
    y = c(2) + r.*sin(tt) ;
    z = zeros(size(x)) ;
    if numel(c)==3 ; z = z + c(3) ; end

    plot3(hg,x,y,z,varargin{:}) ;
end

set(ax,'NextPlot',holdState) ; % restore axes hold state

您现在可以调用此函数而不是 viscircles。我使用 varargin 参数将任何 line 属性 转移到创建的圈子(因此您可以指定 ColorLineWidth 和任何其他典型参数喜欢。

举个例子,我需要重新创建一个与您的类似的曲面,在最大值周围分布有 4x "zero" 个极点:

pc = 0.5 ;  % pole centers
pw = 0.05 ; % pole widths

% surface definition
[X,Y] = meshgrid(-5:.1:5);
R = sqrt(X.^2 + Y.^2) + eps ;
Z = sin(R)./R;
% zero surface values around the defined poles
[idxPoles] = find(abs(X)>=pc-pw & abs(X)<=pc+pw & abs(Y)>=pc-pw & abs(Y)<=pc+pw ) ;
Z(idxPoles)= 0 ;
% display
hs = surf(X,Y,Z) ; shading interp

产生:

现在您可以使用 circles_3D 功能简单地获取您的圈子:

zc = max(max(Z)) ;
circle_pos = [ pc pc zc ; -pc -pc zc ; -pc +pc zc ; +pc -pc zc ] ;
circle_rad = 0.2 * ones(4,1);
h = circles_3d( circle_pos , circle_rad , 'Color','r','LineWidth',2) ;

并得到:


请注意,我制作了此函数,因此它还 return 一个包含您的线条(圆圈)的 hggroup 对象。因此,如果您想稍后 移动 它们,请应用与答案第一部分相同的技巧。