MATLAB:在曲面图上绘制图形

5

我正在用MATLAB绘制一个R^2到R函数的曲面图,然后对其进行颜色映射并从上方观看。

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

它会生成(加上一些额外的代码)类似于以下内容:

enter image description here

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

enter image description here

我想在原始图表之上绘制一个圆形(从上方看)。就像这样...

enter image description here

我似乎无法实现这一点,因为在图表中绘制平面元素会使它们出现在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平面上,因此从上方是不可见的。

enter image description here

如何将我的圆圈绘制在表面图的顶部,以便从上方可见? 当在表面上绘制文本时,会出现类似的问题,但是可以通过指定略高于底层函数z值的z位置值来解决。似乎没有办法指定这些图形元素的z位置。

你应该提供生成R^2 to R函数和表面的定义(和代码)... - Hoki
@Hoki 这是一个任意的曲面。例如:[X, Y] = meshgrid(linspace(-10, 10, 500)); surf(X, Y, X.^2 + Y.^2) - Anti Earth
2个回答

6

也许没有直接的方法来指定由viscircles返回的对象的z位置,但通常情况下后续可以修改任何图形对象的属性和位置(大部分时间都是这样)。


方法一:创建后修改圆形。

如果您计划对图形对象进行修改,首先要做的事情是检索其句柄。因此,在您的情况下,您需要通过指定返回值(其中包含您想要的句柄)来调用viscircles

hg = viscircles(circle_pos, circle_rad);

我没有安装 Image Processing Toolbox,因此无法访问 viscircles 函数。但是从文档中我了解到返回的句柄是一个 hggroup。一个 hggroup 只是一个容器,包含一个或多个更原始图形对象的句柄。在这种情况下,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

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


方法二:自己动手

如果您不想依赖图像处理工具箱,或者根本没有它,那么自己在三维空间中创建圆相对容易。

这里有一个函数,它将以与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和任何其他常见参数)。

为了举例说明,我需要重新创建一个类似于您的表面,其中有4个“零”极点分布在最大值周围:

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

这将产生:

3d surf

现在,您可以使用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) ;

获取并返回: 输入图像描述
请注意,我编写了这个函数,它还返回一个包含您的线条(圆)的hggroup对象。因此,如果您想稍后移动它们,请应用与答案第一部分相同的技巧。

2
好的,这句话的翻译是:“脑海中浮现出几个选项。其中最简单的方法是使用plot3在三维空间中绘制一个标记。”
figure;
peaks;
shading interp;
hold;
x = 0; y = 2; z = 10;
plot3(x, y, z, 'ro', 'MarkerSize', 24);

那样做是可行的,但圆圈始终会看起来面向观察者: plot3 markerplot3 marker in 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);

结果:一个漂亮的三维光晕!

plotting a circle in 3da nice halo


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接