I'm trying to represent a the intersection of two fuzzy sets as a 3d mesh in MatLab.
Here are my sets of vectors:
x = [0.3 0.5 0.7]
y = [0.5 0.7 0.1]
Followed by these statements:
[u,v] = meshgrid(x,y)
w = min(u,v)
mesh(u,v,w)
The x and y ticks seem to be all over the place and do not correlate to the actual index number of each vector i.e. 1 to 3, and the graph should represent the shape of a small triangle/T-norm.
At the moment it looks like this:
Here is an example out of my book I'm following:
Ignore what looks like fractions, they are delimiters. Here is the resulting graph:
After looking up fuzzy sets and intersections, here's what I've come up with. First, let's reproduce the textbook example:
% possible values and associated degrees of truth for F
Fv = 1 : 5;
Ft = [0 0.5 1 0.5 0];
% possible values and associated degrees of truth for D
Dv = 2 : 4;
Dt = [0 1 0];
% determine degrees of truth for fuzzy intersection
It = bsxfun(#min, Ft', Dt);
% plot
h = mesh(Dv, Fv, It);
set(h, 'FaceColor', 'none')
set(h, 'EdgeColor', 'k')
xlim([0 4.5])
ylim([0 5])
xlabel D
ylabel F
view(37.5, 30)
The result is:
Not as pretty as in your book, but the same thing.
Applying the same code to your example yields:
Via the arguments u,v you are telling mesh to use the values in them, i.e. the values from x and y, for the positioning of the data points and corresponding ticks. If you just want positions and ticks at 1, 2, 3, leave these arguments out.
mesh(w)
Related
I have two contour maps in Matlab and each of the two maps has a single curve specifying a single Z-value. I want to super impose the two contour maps so that I can find the single solution where the two z-value curves intersect. How could I go about super imposing the two contour maps?
% the two contour maps are coded the exact same way, but with different z-values
x = 0.05:0.05:1;
y = 0.0:0.05:1;
[X, Y] = meshgrid(x, y);
% Z-value data is copied from excel and pasted into an array
Z = [data]
contourf(X, Y, Z);
pcolor(X, Y, Z); hold on
shading interp
title();
xlabel();
ylabel();
colorbar
val = %z-value to plot onto colormap
tol = %tolerance
idxZval = (Z <= val+tol) & (Z >= val-tol);
plot(X(idxZval), Y(idxZval))[enter image description here][1]
The end result you seek is possible using contourc or using contour specifying the same contours (isolines).
This answer extends this answer in Approach 1 using contourc and provides a simple solution with contour in Approach 2.
You might ask "Why Approach 1 when Approach 2 is so simple?"
Approach 1 provides a way to directly access the individual isolines in the event you require a numerical approach to searching for intersections.
Approach 1
Example Data:
% MATLAB R2018b
x = 0:0.01:1;
y = 0:0.01:1;
[X,Y] = meshgrid(x,y);
Z = sqrt(X.^3+Y); % Placeholder 1
W = sqrt(X.*Y + X.^2 + Y.^(2/3)); % Placeholder 2
Overlay Single Isoline from 2 Contour Plots
Mimicking this answer and using
v = [.5 0.75 .85 1]; % Values of Z to plot isolines
we can visualize these two functions, Z, and W, respectively.
We can overlay the isolines since they share the same (x,y) domain. For example, they both equal 0.8 as displayed below.
val = 0.8; % Isoline value to plot (for Z & W)
Ck = contourc(x,y,Z,[val val]);
Ck2 = contourc(x,y,W,[val val]);
figure, hold on, box on
plot(Ck(1,2:end),Ck(2,2:end),'k-','LineWidth',2,'DisplayName',['Z = ' num2str(val)])
plot(Ck2(1,2:end),Ck2(2,2:end),'b-','LineWidth',2,'DisplayName',['W = ' num2str(val)])
legend('show')
Overlay Multiple Isolines from 2 Contour Plots
We can also do this for more isolines at a time.
v = [1 0.5]; % Isoline values to plot (for Z & W)
figure, hold on, box on
for k = 1:length(v)
Ck = contourc(x,y,Z,[v(k) v(k)]);
Ck2 = contourc(x,y,W,[v(k) v(k)]);
p(k) = plot(Ck(1,2:end),Ck(2,2:end),'k-','LineWidth',2,'DisplayName',['Z = ' num2str(v(k))]);
p2(k) = plot(Ck2(1,2:end),Ck2(2,2:end),'b-','LineWidth',2,'DisplayName',['W = ' num2str(v(k))]);
end
p(2).LineStyle = '--';
p2(2).LineStyle = '--';
legend('show')
Approach 2
Without making it pretty...
% Single Isoline
val = 1.2;
contour(X,Y,Z,val), hold on
contour(X,Y,W,val)
% Multiple Isolines
v = [.5 0.75 .85 1];
contour(X,Y,Z,v), hold on
contour(X,Y,W,v)
It is straightforward to clean these up for presentation. If val is a scalar (single number), then c1 = contour(X,Y,Z,val); and c2 = contour(X,Y,W,val) gives access to the isoline for each contour plot.
I wanted to plot the above function on Matlab so I used the following code
ezplot('-log(x)-log(y)+x+y-2',[-10 10 -10 10]);
However I'm just getting a blank screen. But clearly there is at least the point (1,1) that satisfies the equation.
I don't think there is a problem with the plotter settings, as I'm getting graphs for functions like
ezplot('-log(y)+x+y-2',[-10 10 -10 10]);
I don't have enough rep to embed pictures :)
If we use solve on your function, we can see that there are two points where your function is equal to zero. These points are at (1, 1) and (0.3203 + 1.3354i, pi)
syms x y
result = solve(-log(x)-log(y)+x+y-2, x, y);
result.x
% -wrightOmega(log(1/pi) - 2 + pi*(1 - 1i))
% 1
result.y
% pi
% 1
If we look closely at your function, we can see that the values are actually complex
[x,y] = meshgrid(-10:0.01:10, -10:0.01:10);
values = -log(x)-log(y)+x+y-2;
whos values
% Name Size Bytes Class Attributes
% values 2001x2001 64064016 double complex
It seems as though in older versions of MATLAB, ezplot handled complex functions by only considering the real component of the data. As such, this would yield the following plot
However, newer versions consider the magnitude of the data and the zeros will only occur when both the real and imaginary components are zero. Of the two points where this is true, only one of these points is real and is able to be plotted; however, the relatively coarse sampling of ezplot isn't able to display that single point.
You could use contourc to determine the location of this point
imagesc(abs(values), 'XData', [-10 10], 'YData', [-10 10]);
axis equal
hold on
cmat = contourc(abs(values), [0 0]);
xvalues = xx(1, cmat(1,2:end));
yvalues = yy(cmat(2,2:end), 1);
plot(xvalues, yvalues, 'r*')
This is because x = y = 1 is the only solution to the given equation.
Note that the minimum value of x - log(x) is 1 and that happens when x = 1. Obviously, the same is true for y - log(y). So, -log(x)-log(y)+x+y is always greater than 2 except at x = y = 1, where it is exactly equal to 2.
As your equation has only one solution, there is no line on the plot.
To visualize this, let's plot the equation
ezplot('-log(x)-log(y)+x+y-C',[-10 10 -10 10]);
for various values of C.
% choose a set of values between 5 and 2
C = logspace(log10(5), log10(2), 20);
% plot the equation with various values of C
figure
for ic=1:length(C)
ezplot(sprintf('-log(x)-log(y)+x+y-%f', C(ic)),[0 10 0 10]);
hold on
end
title('-log(x)-log(y)+x+y-C = 0, for 5 < C < 2');
Note that the largest curve is obtained for C = 5. As the value of C is decreased, the curve also becomes smaller, until at C = 2 it completely vanishes.
I am trying to plot a zplot in Matlab that displays a unit circle, centered at 0 along with the poles and zeros of the plot. I am not allowed to use any other matlab function such as zplane or pzplot to do this. So far I am able to plot a unit circle just fine but I am having trouble getting my plot to display more of the axis without warping my circle. I also am having a heard time finding the poles and zeros of my function and also how to display the poles as little x's and the zeros as little o's on my plot. Any help would be greatly appreciated! My assignment looks like this and must correctly handle cases such as
zplot([0 1 1], [0 1]);
zplot([0 1 1], [0 0 1]);
function zplot(b, a)
% ZPLOT Plot a zero-pole plot.
-1 -nb
B(z) b(1) + b(2)z + .... + b(nb+1)z
H(z) = ---- = ---------------------------------
-1 -na
A(z) a(1) + a(2)z + .... + a(na+1)z
% zplot(b, a) plots the zeros and poles which determined by vectors b and a
% The plot includes the unit circle and axes for reference, plotted in black.
% Each zero is represented with a blue 'o' and each pole with a red 'x' on the
%plot.
xmin;
xmax;
ymin;
ymax;
% vector of angles at which points are drawn
angle = 0:2*pi/100:2*pi;
% Unit radius
R = 1;
% Coordinates of the circle
x = R*cos(angle);
y = R*sin(angle);
% Plot the circle
plot(x,y);
axis ([xmin, xmax, ymin, ymax]);
grid on;
end
If you can't use pzplot() it is not hard. Here is a hint:
num = [1 4 1];%numerator coefficients of transfer function
den = [1 2 1];%denominator coefficients
z = roots(num)%zeros
p = roots(den)%poles
angle = 0:2*pi/100:2*pi;
xp = cos(angle);
yp = sin(angle);
figure(1)
scatter(z,zeros(length(z),1),'o');
hold on
scatter(p,zeros(length(p),1),'x');
plot(xp,yp);
axis equal
The output
Note that I haven't dealt with imaginary poles/zeros in this example. You'll need to calculate the proper x,y coordinates for a given imaginary pole or zero. (all the poles/zeros in this example are real, not imaginary)
Given a transfer function G, you can use the pzplot() command and add a circle to it.
G = tf([1 4 1],[1 2 1]);
angle = [0:0.1:2*pi+0.1];
xp = cos(angle);
yp = sin(angle);
figure(1)
hold on
pzplot(G);
plot(xp,yp);
axis equal;
This should give you the pole-zero plot with x's for poles, o's for zeros, and the unit circle.
Here is the result.
I had to plot this in matlab :
so I wrote the following code:
x=[0.9 1 0.9 -0.9 0.7 0.7 -0.9 0.9];
y=[-1 0 1 -0.5 -0.8 0.8 -0.4 -1];
plot(x,y);
but this gives me:
Is this method insufficient to draw the first figure....Is there some other short method for this...
You can do better positioning your data points
nPoints = 7;
th = linspace(-2*pi, 2*pi, 2*nPoints+1);%// extra point to close the curve
r = 1;
x = r*cos(th);
y = r*sin(th);
scatter( x, y, 'ro' );
hold on;
plot( x(1:2:end), y(1:2:end), 'b-' );
axis equal;
Resulting with:
BTW, this code works for any odd nPoints - just try ;)
It seems to me that you want to construct a star polygon, which has the property that all points are equidistant to its neighboring points, and all points lie on the same circle.
First, we generate the desired angles a (measured from the x-axis to a line that connects the origin with the desired point, see wikipedia). Based on the polygon, we rearrage the angles in such a way that a desired number of points is skipped (in the code below, this is done by using among others repmat - but many alternatives exist).
To convert the angles to actual points in the plane, we take sine and cosine values, and then we can plot the dots and lines. Putting this together results in the following code, which results in the dersired figure
n = 7;
a = linspace(0,2*pi,n+1);
skip = 1;
b = [repmat(a(1:end-1),1,skip+1) a(end)];
a = b(1:skip+1:end);
figure;
clf;
hold on;
plot(cos(a),sin(a),'b-');
plot(cos(a(1:end-1)),sin(a(1:end-1)),'ro');
axis([-1 1 -1 1])
axis equal
A little less involved would be to compute the vector a like this:
a = mod(linspace(0,(skip+1)*2*pi,n+1),(skip+1)*2*pi);
I tried manually:
x = [-0.4 0.6 1 0.6 -0.4 -0.8 -0.8];
y = [-0.9 -0.7 0 0.7 0.9 0.4 -0.4];
x_ = [x,x];
y_ = [y,y];
figure;
hold on;
for ii=1:numel(x),
scatter(x(ii),y(ii),'ro');
plot([x_(ii),x_(ii+1+1)],[y_(ii),y_(ii+1+1)],'b-');
end
axis([-1 1 -1 1]);
And I get his:
I am stuck with this problem for a long time now. I have a polygonal region (lets say, a hexagon). I can calculate the values of certain function at any point inside the polygon. Now I need to create a filled contour (using contourf in MATLAB) of this data. How do I go about it. I found some discussion on this topic at the link below (page 121)
http://www-personal.umich.edu/~jpboyd/eng403_chap4_contourplts.pdf
This works somewhat ok but it still produces jagged edges which I don't want. Anyone has any suggestion on this problem? Thanks. Here is my code
close all
Node = [ 1.0 0
0.5 0.8660
-0.5 0.8660
-1.0 0
-0.5 -0.8660
0.5 -0.8660];
[x,y] = meshgrid(-1:0.1:1,-1:0.1:1);
N = zeros(size(x));
for i=1:size(x,2)
for j=1:size(y,2)
p = [x(i,j) y(i,j)];
IN = inpolygon(p(1),p(2),Node(:,1),Node(:,2));
if IN
N(i,j)= rand;
else
N(i,j)= NaN;
end
end
end
figure
contourf(x,y,N,'LineStyle','none'), hold on;
xlabel('X'), ylabel('Y'), axis equal; axis off; colorbar;
line([Node(:,1);Node(1,1)],[Node(:,2);Node(1,2)],'Color',[1 1 1],'LineWidth',2.0)
clear IN i j p x y
You're using a square grid to sample a hexagonal area. This will indeed lead to boundary problems.
A better solution (but still not quite optimal) is to use a hexagonal grid:
%# define hexagon
Node = [ 1.0 0
0.5 0.8660
-0.5 0.8660
-1.0 0
-0.5 -0.8660
0.5 -0.8660];
%# Generate hexagonal grid
Rad3Over2 = sqrt(3) / 2;
[x, y] = meshgrid(0:51);
n = size(y,1);
x = Rad3Over2 * x;
y = y + repmat([0 0.5],[n,n/2]);
%# re-scale to -1..1
x = 2*x/max(x(:))-1;
y = 2*y/max(y(:))-1;
%# insode-polygon check
N = zeros(size(x));
for i=1:size(x,2)
for j=1:size(y,2)
p = [x(i,j) y(i,j)];
IN = inpolygon(p(1),p(2),Node(:,1),Node(:,2));
if IN
N(i,j)= rand;
else
N(i,j)= NaN;
end
end
end
%# make contour plot
figure(1)
contourf(x,y,N,'LineStyle','none'), hold on;
xlabel('X'), ylabel('Y'), axis equal; axis off; colorbar;
line([Node(:,1);Node(1,1)],[Node(:,2);Node(1,2)],'Color',[1 1 1],'LineWidth',2.0)
If you want even better coverage, you'll have to devise a grid that better covers your area and/or up the number of sample points.
For arbitrary irregular areas, you might want to experiment with irregular/random grids, distributed such that there are more points close to the boundaries, than there are in the middle of the area.
Suppose you have a function defined on a hexagon. Then take some square that contains the hexagon.
A simple first test could be to extend your function on the square to take the value = 0 for points outside of the hexagon.
Depending on the range of your function this may, or may not, give you a good answer.
If this doesn't work, then find the min of the function on the hexagon using min(min(A))) for an nxn matrix A. Then define the function to be min(min(A)) - 1.0 outside of the hexagon but in the square.
Then use contourf(x, y, z, v) where v is a vector of values for the output, so take v(1) = min(min(A)) - 1.0, and v(2:n) = linspace(min(min(A)), max(max(A)), n) for some integer n. You can probably specify the color of the level set min(min(A)) - 1.0 to be white, but I've never done this. I've had to do something like this before, and setting the function = 0 outside of he hexagon was enough.
If your function can only be evaluated inside the polygonal region, then my hexagonal grid answer still stands. However, if your function can be (or modified to be) evaluated outside the polygon, you might want to use a cheat:
figure(1), clf, hold on
%# External contour, square.
x1 = [-3 -3 +3 +3 -3]/2;
y1 = [-3 +3 +3 -3 -3]/2;
%# internal contour, some polygon
x2 = [1.0 0.5 -0.5 -1.0 -0.5 0.5];
y2 = [0 0.8660 0.8660 0 -0.8660 -0.8660];
%# convert to patches
[f, v] = poly2fv({x1, x2}, {y1, y2});
patch(...
'Faces' , f,...
'Vertices' , v,...
'FaceColor', get(0, 'defaultuicontrolbackgroundcolor'), ...
'EdgeColor', 'none'...
);
%# Generate function for contourplot
[x, y] = meshgrid(-2.8/2:0.1:2.8/2);
N = rand(size(x));
%# make contour plot
contourf(x,y,N,'LineStyle','none'), hold on;
xlabel('X'), ylabel('Y'), axis equal;
axis off; colorbar;
It basically creates your contour plot on a square region, and overlays a mask with a hexagonal hole in it, so it looks like it's only a contour of the hexagonal. I suspect it is a lot easier to tweak your function to allow function evaluations outside the region, then it is to (re-)invent some sort of grid that contains the boundaries.