#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
Который производит:
Теперь вы можете просто получить свои круги с 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);
Это сработает, но круг всегда будет выглядеть обращенным к зрителю:
Кроме того, вы можете построить круг в 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!