This question already has answers here:
Draw 3d Inequality on Matlab
(1 answer)
matlab - plot inequality in 3d with surf
(1 answer)
Closed 1 year ago.
I want to plot a 3d region in MATLAB bounded from a set of inequalities.
For example:
0 <= x <= 1
sqrt(x) <= y <= 1
0 <= z <= 1 - y
I found a 2d example that someone has done on this site but I'm not sure how to convert that to 3d. How to plot inequalities.
Edit:
From #Tobold's help I modified the code to restrict the points that are plotted to those that are defined by all three regions, but it plots only 2 or 3 points. It looks like the points in the vectors X1, Y1 and Z1 are right but for some reason its plotting only a few. Any ideas why it is only plotting a few points from the X1, Y1 and Z1 vectors instead of all of them?
[X,Y,Z]=meshgrid(0:0.1:1,0:0.1:1,0:0.1:1); % Make a grid of points between 0 and 1
p1=0.1; p2=0.2; % Choose some parameters
X1 = (X >= 0 & X <= 1) & (Y >= sqrt(X) & Y <= 1) & (Z >= 0 & Z <= 1 - Y);
Y1 = (X >= 0 & X <= 1) & (Y >= sqrt(X) & Y <= 1) & (Z >= 0 & Z <= 1 - Y);
Z1 = (X >= 0 & X <= 1) & (Y >= sqrt(X) & Y <= 1) & (Z >= 0 & Z <= 1 - Y);
ineq1 = (X >= 0 & X <= 1) * 2;
ineq2 = (Y >= sqrt(X) & Y <= 1) * 4;
ineq3 = (Z >= 0 & Z <= 1 - Y) * 8;
all = ineq1 & ineq2 & ineq3;
colors = zeros(size(X))+ineq1+ineq2+ineq3;
scatter3(X1(:),Y1(:),Z1(:),3,colors(:)','filled')
You can do almost the same thing as in the 2d case that you linked to. Just write down your three inequalities, use a 3d meshgrid, multiply each inequality with a number from a set of three numbers that has unique subset sums (e.g. 2, 4, 8) and use scatter3:
[X,Y,Z]=meshgrid(0:0.1:1,0:0.1:1,0:0.1:1); % Make a grid of points between 0 and 1
p1=0.1; p2=0.2; % Choose some parameters
ineq1 = (X >= 0 & X <= 1) * 2;
ineq2 = (X >= sqrt(X) & Y <= 1) * 4;
ineq3 = (Z >= 0 & Z <= 1 - Y) * 8;
colors = zeros(size(X))+ineq1+ineq2+ineq3;
scatter3(X(:),Y(:),Z(:),3,colors(:),'filled')
I've been trying to figure out the same thing, and the trick is to make the size of everything not in the intersection 0. Tobold's scatter3 line uses '3' as the option for size, meaning all points will show up as point 3. This can be substituted for a matrix of equal size to X1 with the set of sizes. The easiest way to do this is just make s = 3*all:
all = ineq1 & ineq2 & ineq3;
colors = zeros(size(X))+all;
sizes = 3 * all;
scatter3(X1(:),Y1(:),Z1(:),sizes,colors(:)','filled')
That should get you just the area in the intersection.
--
edit: The color variable needs to change too. You just want the intersection, not the other inequalities.
I don't understand several things in the code that you wrote as modification of #Tobold's help. For example what are the parameters p1 and p2 doing in your code?
Anyway, The code plotting only the points of your grid satisfying all of your inequalities;
[X,Y,Z]=meshgrid(0:0.1:1,0:0.1:1,0:0.1:1);
ineq1 = (X >= 0 & X <= 1);
ineq2 = (Y >= sqrt(X) & Y <= 1);
ineq3 = (Z >= 0 & Z <= 1 - Y);
all = ineq1 & ineq2 & ineq3;
scatter3(X(all),Y(all),Z(all),'b','filled')
The result is brought in the following image.
Related
I'm trying to plot a function subject to three constraints (see code)
Now I tried the following
function value = example(x1, x2)
if x1 < 0 || x2 < 0 || x1+2*x2 > 6
value = NaN;
else
value = abs(x1 - x2) + exp(-x1 - x2);
end
[X, Y] = meshgrid(-10:10, -10:10);
Z = example(X,Y);
surf(X, Y, Z)
Now, this raises an error since the if clause cannot be evaluated for inputs X and Y. Any idea how to make this work?
As #Cris mentioned, use logical indexing.
The basic idea is (x1 < 0 | x2 < 0 | x1+2*x2 > 6) will gives you a matrix (same size as value) of zeros and ones. The positions of ones correspond to the true condition. Try this:
function value = example(x1, x2)
value = abs(x1 - x2) + exp(-x1 - x2);
value(x1 < 0 | x2 < 0 | x1+2*x2 > 6) = NaN;
Output:
I would like to produce a piecewise constant surface which is zero outside of some rectangle. More specifically, for t = (x,y) in R^2, I want
f(t) = 1 when 5<y<10 and 0<x<1;
-1 when 0<y<5 and 0<x<1;
1 when -5<y<0 and 0<x<1;
0 elsewhere
But, the surface I get doesn't look like what I want. I'm somewhat of a Matlab novice, so I suspect the problem is in the logical operators. My code is:
x = -2:.01:2; y = -15:15
[X,Y] = meshgrid(x,y); %Make domain
for i = 1:numel(X) %Piecewise function
for j = 1:numel(Y)
if Y(j) >= 0 && Y(j)<= 5 && X(i)>=0 && X(i)<=1
h2(i,j)= -1;
elseif Y(j)>5 && Y(j) <= 10 &&X(i)>=0 &&X(i)<=1
h2(i,j) = 1;
elseif Y(j)<0 && Y(j)>=-5 &&X(i)>=0 &&X(i)<=1
h2(i,j) = 1;
elseif X(i) <0 || X(i)>1 || Y(j)<-5 || Y(j)>10
h2(i,j) = 0;
end
end
end
%Normalize
C = trapz(abs(h2));
c = trapz(C);
h2 = c^(-1)*h2;
Thank you for your help and please let me know if you'd like me to specify more clearly what function I want.
You can very easily achieve what you want vectorized using a combination of logical operators. Avoid using for loops for something like this. Define your meshgrid like you did before, but allocate a matrix of zeroes, then only set the values within the meshgrid that satisfy the requirements you want to be the output values of f(t). In other words, do this:
%// Your code
x = -2:0.1:2; y = -15:15;
[X,Y] = meshgrid(x,y); %Make domain
%// New code
Z = zeros(size(X));
Z(Y > 5 & Y < 10 & X > 0 & X < 1) = 1;
Z(Y > 0 & Y < 5 & X > 0 & X < 1) = -1;
Z(Y > -5 & Y < 0 & X > 0 & X < 1) = 1;
mesh(X,Y,Z);
view(-60,20); %// Adjust for better angle
The above code allocates a matrix of zeroes, then starts to go through each part of your piecewise definition and searches for those x and y values that satisfy the particular range of interest. It then sets the output of Z to be whatever the output of f(t) is given those constraints. Take note that the otherwise condition is already handled by setting the whole matrix to be zero first. I then use mesh to visualize the surface, then adjust the azimuthal and elevation angle of the plot for a better view. Specifically, I set these to -60 degrees and 20 degrees respectively. Also take note that I decreased the resolution of the x values to have a step size of 0.1 instead of 0.01 for a lesser amount of granularity. This is solely so that you can see the mesh better.
This is the graph I get:
You can just use logical indexing:
x = -2:.01:2; y = -15:15;
[X,Y] = meshgrid(x,y); %// Make domain
h2=zeros(size(X));
h2(5<Y & Y<10 & 0<X & X<1)=1;
h2(0<Y & Y<5 & 0<X & X<1)=-1;
h2(-5<Y & Y<0 & 0<X & X<1)=1;
This statement: 5<Y & Y<10 & 0<X & X<1 returns a matrix of 1's and 0's where a 1 means that all 4 inequalities are satisfied, and a 0 means at least one is not. Where that matrix has a one, h2 will be modified to the value you want.
If I have a function f(x) which is defined as
f(x) = x^2; x>0 & x<=1
= x^3; x>1 & x<2
= 2*x; elsewhere
How do I plot this in Matlab in the same graph?
I would do this without fplot :
x = 0:0.1:3;
x1 = x(x>0 & x<=1);
x2 = x(x>1 & x<2);
x3 = x(x>2);
y1 = (x1).^2;
y2 = (x2).^3;
y3 = 2*(x3);
plot([x1 x2 x3], [y1 y2 y3])
You can define a set of x values (say between 4 <= x <= 4), then apply 2*x to every value within this interval. After, search for those x values that are within the intervals of the other functions and set those values to what they should be within those intervals. As such, try something like this:
x = -4 : 0.001 : 4;
y = 2*x;
y(x > 0 & x <= 1) = x(x > 0 & x <= 1).^2;
y(x > 1 & x < 2) = x(x > 1 & x < 2).^3;
plot(x,y);
grid;
This is what I get:
I used the following simple code to check the properties of elseif command in MATLAB:
x = 10;
if x < 0
y = x;
elseif 0 <= x < 2
y = 3*x;
elseif x >= 2
y = 8*x;
end
y
I would have expected the result of this to be 80 since x >= 2. But something amazing happened! The result is 30, not 80!
But why? Any ideas?
Update: when I change the code (as recommended in the answers) to
x = 10;
if x < 0
y = x;
elseif (0 <= x) && ( x < 2 )
y = 3*x;
elseif x >= 2
y = 8*x;
end
y
I get 80 as expected. It's that double condition that threw me off.
When you write
if 0 <= x < 2
you are really writing (without realizing it)
if (0 <= x) < 2
Which is evaluated as
if (true) < 2
which is true, since true evaluates to 1.
So here is what is happening, line by line:
x = 10; % x is set to 10
if x < 0 % false
y = x; % not executed
elseif 0 <= x < 2 % condition is (true) < 2, thus true
y = 3*x; % y is set to 3*x, i.e. 30
elseif x >= 2 % since we already passed a condition, this is not evaluated
y = 8*x; % skipped
end % end of composite if
y % display the value of y - it should be 30
As an aside, when you use scalars, you should really use the && operator, not the & operator. See for example What's the difference between & and && in MATLAB?
0 <= x < 2 doesn't behave as you may expect. Use (0 <= x) & (x < 2)
How does 0 <= x < 2 behave? It is evaluated from left to right. First 0 <= x gives 1 (true), and then 1 < 2 gives 1 (true). So the condition gives true, not false as you would expect.
Since the second condition in your code (0 <= x < 2) is true, you get a value 30 for y. Changing the condition to (0 <= x) & (x < 2) you get a value 80 for y.
I have the following function:
f(t) = 0 if t < 0
f(t) = 2*t^2 - 4*t +3 if 1 <= t < 2
f(t) = Cos(t) if 2 <= t
I am a new MATLAB user, and I do not how to plot the function on a single figure over the range 0<=t<=5.
Any ideas about What I have to do?
Write a function for your Laplace formula.
Something like this
function [ft] = func(t)
if t <= 0
ft = 0;
elseif t > 0 && t < 2
ft = 2 * t^2 - 4 * t + 3;
elseif t >= 2
ft = cos(t);
end
You can then plot the function with fplot, the second parameter defines the plotting range.
fplot('func', [0, 5])
thanks for your help but I could not implement any code or commands to get the answer. Instead of, I was lucky and I found an example and the MATLAB commands are as follow:
x=linspace(0,5,3000);
y=(0*x).*(x<1) + (2*(x.^2)-(4.*x)+3).*((1<=x) & (x<2))
+ (cos(x)).*(2<=x);
plot(x,y, '.'), grid
axis([0 5 -2 4])
title ('Plot of f(t)'), xlabel('t'), ylabel('f(t)')
If you mean limiting x axis, then after using plot use
xlim([xmin xmax])
In your case
xlim([0 5])
Use ylim for limiting y axis
Ok, I think I misunderstood you
Also I think, you've made mistake in your formulas
f(t) = 0 if 0<= t < 1
f(t) = 2*t^2 - 4*t +3 if 1 <= t < 2
f(t) = Cos(t) if 2 <= t
figure;
hold on;
x = 0:0.1:0.9; y = 0 * x; plot( x, y );
x = 1:0.1:1.9; y = 2 * x * x - 4 * x + 3; plot( x, y );
x = 2:0.1:5; y = cos( x ); plot( x, y );