MATLAB: рисование поверх графика поверхности

#matlab #plot #surface

#matlab #график #Поверхность

Вопрос:

Я строю функцию R ^ 2 to R в MATLAB в качестве графика поверхности, который я раскрашиваю и просматриваю сверху.

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

Он создает (с некоторым дополнительным кодом) что-то вроде

введите описание изображения здесь

хотя истинную природу функции (для понимания этого вопроса) лучше наблюдать под таким углом, как:

введите описание изображения здесь

Я хочу нарисовать круг поверх моего исходного графика (видно сверху). Что-то вроде…

введите описание изображения здесь

Однако, похоже, я не могу этого добиться, поскольку при построении элементов в плоскости на графиках они отображаются на оси xy, которая покрывается моим графиком поверхности. Например, вызов

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

после того, как мой график поверхности не приводит к появлению видимых кругов при просмотре сверху. Масштабирование и поворот показывают, что эти круги были нанесены на плоскость xy и поэтому невидимы сверху.

введите описание изображения здесь

Как мне нанести мои круги поверх графика поверхности, чтобы они были видны сверху? Аналогичная проблема возникает при построении text графика поверх поверхности, но ее можно устранить, указав значение положения z чуть выше значения z базовых функций. Похоже, нет никакого способа указать положение z этих графических элементов.

Комментарии:

1. Вы должны дать определение (и код) для генерации вашей R^2 to R функции и поверхности…

2. @Hoki это произвольная поверхность. Например. [X, Y] = meshgrid(linspace(-10, 10, 500)); surf(X, Y, X.^2 Y.^2)

Ответ №1:

Возможно, не существует прямого способа указать z положение объектов, возвращаемых viscircles , но в целом (в большинстве случаев) есть способ впоследствии изменить свойства и положение любого графического объекта.


Метод 1: изменение окружностей после создания.

Если вы планируете вносить изменения в графический объект, первое, что нужно сделать, это всегда извлекать его handle . Итак, в вашем случае вам нужно будет вызвать viscircles , указав возвращаемое значение (которое будет содержать handle нужное вам значение).:

 hg = viscircles(circle_pos, circle_rad);
  

У меня нет Image Processing Toolbox , поэтому у меня нет доступа к viscircles функции. Однако я прочитал из документации, что возвращаемый дескриптор является hggroup . An hggroup — это просто контейнер, содержащий один или несколько handles более примитивных графических объектов. В этом случае hggroup содержит дескрипторы 4 lines (ваши 4 круга).

Самый простой способ преобразовать все объекты в hggroup — использовать hgtransform объект. Мы определим преобразование перевода и 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 (не только максимальное значение поверхности).


Способ 2: сделай сам

Если вы не хотите полагаться на инструментарий обработки изображений или если у вас его вообще нет, относительно легко создавать круги в 3D-пространстве самостоятельно.

Вот функция, которая будет создавать окружности способом, сравнимым с 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 свойства созданным окружностям (так что вы можете указать Color , LineWidth , и любой другой типичный параметр, который вам нравится.

Для примера мне нужно воссоздать поверхность, сравнимую с вашей, с 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 amp; abs(X)<=pc pw amp; abs(Y)>=pc-pw amp; 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:

На ум приходит несколько вариантов.

Самым простым будет нанесение маркера в 3d с помощью plot3 :

 figure;
peaks;
shading interp;
hold;
x = 0; y = 2; z = 10;
plot3(x, y, z, 'ro', 'MarkerSize', 24);
  

Это сработает, но круг всегда будет выглядеть обращенным к зрителю:
маркер plot3маркер plot3 в 3d

Кроме того, вы можете построить круг в 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!

построение окружности в 3dприятный ореол