How to use plot3 restrict to a certain region in Matlab? - matlab

For example, I want to plot the function
f(x,y) =sin(x^2+y^2)/(x^2+y^2), x^2+y^2 <=4π
In Mathematica, I can do it as following:
Plot3D[Sin[x^2 + y^2]/(x^2 + y^2), {x, -4, 4}, {y, -4, 4},
RegionFunction -> (#1^2 + #2^2 <= 4 Pi &)]
Where the RegionFunction specified the region of x,y to plot.

Here's a not particularly elegant solution that sets the function values of the region you don't want to see to -infinity.
[x, y] = meshgrid(-4:0.1:4, -4:0.1:4);
z = sin(x.^2+y.^2)./(x.^2+y.^2);
idx = x.^2 + y.^2 > 4*pi;
z(idx) = -Inf;
surf(x, y, z); axis vis3d;
Edit. Actually, if you try a finer grid (say -4:0.01:4) and add shading interp it doesn't look too bad.

A slight variation to 3lectrologos's solution, with emphasis on keeping what you want:
x = -4*pi:0.01:4*pi;
y = -4*pi:0.01:4*pi;
[X,Y] = meshgrid(x,y);
Clean = (X.^2 + Y.^2)<=4*pi;
Y = Y.*Clean;
X = X.*Clean;
X(~any(X,2),:) = [];
X(:, ~any(X,1)) = [];
Y(~any(Y,2),:) = [];
Y(:, ~any(Y,1)) = [];
F = sin(X.^2+Y.^2)./(X.^2+Y.^2);
mesh(X,Y,F)
Note that in this case, you need to make sure that (0,0) is in your solution profile.
Edit: compressing matrices for easier plotting

Related

Why is my Z limit not being set even though I specified it?

See my code below:
x = linspace(-2*pi,2*pi,100);
y = linspace(-2*pi,2*pi,100);
[X,Y] = meshgrid(x,y);
for t = linspace(0,2*pi,400);
Z = sin(sqrt(X.^2 + Y.^2 + t)) ./ (X.^2 + Y.^2 + t);
figure(1); surf(X,Y,Z);
pause(0.01)
surf(X,Y,Z);
az = 90;
el = 25;
figure(2);view(az,el);
xlim([-10,10]);
ylim([-10,10]);
zlim([-1,1]);
end
Why does z limit still keep on changing even though set to [-1 1]?.
Your problem is that you keep recreating the entire plot anew every time you call surf in your loop, thus discarding any previous changes you made to the axes limits, etc. When animating plots, it's much more efficient (and easier to control the axes settings) if you use set to update graphics objects instead of completely reproducing them, as illustrated here.
Here's a better approach to create the animation you want:
% Initialize data:
x = linspace(-2*pi, 2*pi, 100);
y = linspace(-2*pi, 2*pi, 100);
[X, Y] = meshgrid(x, y);
Z = sin(sqrt(X.^2 + Y.^2)) ./ (X.^2 + Y.^2);
% Create plot objects and set axes settings:
hSurf = surf(X, Y, Z);
view(90, 25);
xlim([-10 10]);
ylim([-10 10]);
zlim([-1 1]);
% The animation loop:
for t = linspace(0, 2*pi, 400)
Z = sin(sqrt(X.^2 + Y.^2 + t)) ./ (X.^2 + Y.^2 + t); % Recalculate Z
set(hSurf, 'ZData', Z); % Update surface Z data
pause(0.01); % Pause/refresh plot
end
I believe the view() function overrides/disregards magnitudes of x y and z.
Edit:
view([x,y,z]) sets the view direction to the Cartesian coordinates x, y, and z. The magnitude of (x,y,z) is ignored.
From here

Efficiently Plot Markers of varying individual size

The plot function allows us to plot all markers with a constant size s.
figure;
x = -10 : 10;
y = x .^ 2;
s = 10;
plot(x, y, 'bo', 'MarkerSize', s);
Suppose instead we would like each marker to have some individual size sx. For example, sx = abs(x) + 1.
One way to achieve this would be to use a for loop.
figure;
x = -10 : 10;
y = x .^ 2;
sx = abs(x) + 1;
hold on;
for i = 1 : length(x)
plot(x(i), y(i), 'bo', 'MarkerSize', sx(i));
end
This works well enough for small number of x. However, what if x is larger? For example, x = -100 : 0.01 : 100.
This now takes significantly longer, while plot(x, y, 'bo', 'MarkerSize', 100) would still complete almost instantly. Ideally, we would be able to do something such as plot(x, y, 'bo', 'MarkerSize', sx) where sx is a vector of sizes with each entry in sx corresponding to an entry in x and y. Unfortunately, that would give an error of Value not a numeric scalar.
Is there an efficient way to plot markers where each marker have varying individual sizes?
What you're trying to do is possible using scatter instead of plot as follows:
scatter(x,y,abs(x)+1)

ContourPlot and inequalitie plot together

Im new to matlab and I want to plot a ContourPlot together with two inequalities but I dont know how. The function that I want to plot its ContourPlot is something like this:
Z = (X-2).^2 + (Y-1).^2;
and here are the two inequalities:
ineq1 = X.^2 - Y <= 2;
ineq2 = X + Y <= 2;
this is what I have dodne so far:
[X,Y] = meshgrid(-4:.2:4,-4:.2:4);
Z = (X-2).^2 + (Y-1).^2;
[C,h] = contour(X,Y,Z);
clabel(C,h)
ineq1 = X.^2 - Y <= 2;
ineq2 = X + Y <= 2;
range = (-4:.2:4);
hold on
plot(range,ineq1, range, ineq2)
hold off
but this does not feel right.
What I want to do is to visualize an optimization problem. First I want to plot the ContourPlot of the function and then the possible areas in that same plot, It would be great if I could show the intersection areas too.
If you want to draw the boundaries of the inequalities onto the contour plot, you can do this with line.
[X,Y] = meshgrid(-4:.2:4,-4:.2:4);
Z = (X-2).^2 + (Y-1).^2;
[C,h] = contour(X,Y,Z);
clabel(C,h)
x_vect = (-4:.05:4);
y_ineq1 = x_vect.^2 - 2;
y_ineq2 = 2 - x_vect;
line(x_vect, y_ineq1);
line(x_vect, y_ineq2);
Coloring the intersection area is a bit more tricky, and I'm not sure if it's exactly what you want to do, but you could look into using patch, something like
% Indexes of x_vect, y_ineq1 and y_ineq2 for region where both satisfied:
region_indexes = find(y_ineq1<y_ineq2);
region_indexes_rev = region_indexes(end:-1:1);
% To plot this area need to enclose it
% (forward along y_ineq1 then back along y_ineq2)
patch([x_vect(region_indexes),x_vect(region_indexes_rev)],...
[y_ineq1(region_indexes),y_ineq2(region_indexes_rev)],...
[1 0.8 1]) % <- Color as [r g b]
% May or may not need following line depending on MATLAB version to set the yaxes
ylim([-4 4])
% Get the original plot over the top
hold on
[C,h] = contour(X,Y,Z);
clabel(C,h)
hold off

Contour plot for 3D vector

I am trying to produce a contour plot for the 3D vectors returned by a custom function in the xy plane where z = 0.
I tried this but I just get an empty graph:
% Stand in for the real function I want to plot.
f = #(x, y, z) [x ^ 2, y ^ 2, x * y + z];
x = linspace(-5, 5, 50);
y = linspace(-5, 5, 50);
z = zeros(length(x), length(y), 3);
% I know this can be vectorized but the function I really want to graph can't
% be.
for i = 1:length(x)
for j = 1:length(y)
z(i, j, :) = f(x(i), y(j), 0);
end
end
figure;
axis equal;
contour(x, y, z);
You should mention what your axis will be. You have x,y and 3 outputs from f.
If you consider 3 outputs of your f as the ones to be plotted then you should use,
contour(z(:,:,1),z(:,:,2),z(:,:,3));
Which will give you this,
I think what you are looking for, is a function with one output, like,
f = #(x, y,z) [x ^ 2 + y ^ 2 + x * y + z ];
x = linspace(-5, 5, 50);
y = linspace(-5, 5, 50);
z = zeros(length(x), length(y));
for i = 1:length(x)
for j = 1:length(y)
z(i, j) = f(x(i), y(j),0);
end
end
contour(x,y,z,20);

Using contour to plot function

I try to use contour to plot this function
3y + y^3 - x^3 = 5
I try contour(3*y+y^3-x^3-5) but it doesn't work.
How can I use contour to plot this function?
Are x and y properly defined as 2x2 matrices? If so then the "power" operator needs to be done on a component-wise basis (.^3 instead of ^3).
This works:
[x,y] = meshgrid(-2:.2:2,-2:.2:2);
contour(3*y+y.^3-x.^3-5)
Maybe you can try fcontour, which plots the contour lines of the function z = f(x,y) for constant levels of z over the default interval [-5 5] for x and y.
f = #(x,y) 3*y + y.^3 - x.^3 - 5;
fcontour(f)
Output:
I'm not convinced this addresses all parts of your question but it's a start. If you absolutely want contour to call a function, you can adjust my example to contour(X,Y,fh(X,Y)).
Better Approach
fh=#(x,y) 3*y + y.^3 - x.^3 -5; % <--- This is your function
x = (-4:.25:4)';
y = (-2:.25:2)';
[X,Y] = meshgrid(x,y);
Z = fh(X,Y);
contour(X,Y,fh(X,Y))
The Direct Approach (not preferred but works)
Notice the Z is transposed to make this work.
fh=#(x,y) 3*y + y.^3 - x.^3 -5; % <----this is your function
X = (-4:.25:4)';
Y = (-2:.25:2)';
Z = zeros(length(X),length(Y));
for i = 1:length(X)
for j = 1:length(Y)
xi = X(i);
yj = Y(j);
Z(i,j) = fh(xi,yj);
end
end
contour(X,Y,Z','LevelList',-60:10:60,'ShowText','on','LineWidth',1.4) % Fancied it up a bit