I had plotted a polygon, and used inpolygon matlab function to find the in and on points with respect to the polygon, however, the inpolygon matlab function did not give me logical results, how can i find accurately the points outside the polygon?
This is my code.
nb_lignes = size(image_in1,1);
nb_colonnes = size(image_in1,2);
[Xq,Yq] =
meshgrid(1:nb_colonnes,1:nb_lignes);%grille du cube
[in,on] = inpolygon(Xq,Yq,X1,Y1);
out= ~inpolygon(Xq,Yq,X1,Y1);
f=numel(Xq(in));
p=numel(Xq(on));
figure
plot(X1,Y1) % polygon
axis equal
hold on
plot(Xq(in),Yq(in),'r+') % points inside
plot(Xq(~in),Yq(~in),'bo') % points outside
plot(out,'y')
hold off
Related
I have a bunch of 2 dimensional vectors in Matlab. If I plot them in two dimension space using scatter they fill an area which is not convex. Is there ay way to simply draw only the border of the area? I have tried hist plus contour or convex hull but they do not do the job.
From matlab help:
x = gallery('uniformdata',[10,1],0);
y = gallery('uniformdata',[10,1],1);
DT = delaunayTriangulation(x,y);
k = convexHull(DT)
figure
plot(DT.Points(:,1),DT.Points(:,2), '.','markersize',10);
hold on
plot(DT.Points(k,1),DT.Points(k,2),'r')
hold off
I am generating a scatter plot containing data from multiple sources, as displayed below.
I would like to be able to generate a curve surrounding an arbitrary query point and passing through points on scatter plot. Final goal is to calculate the area between the lines on the plot.
I have implemented solution using finding points with knnsearch in a circular fashion and then applying hampel filter to eliminate noise. In the example below, I have selected a point right about in the middle of the blue-shaded area. As you can see, the result is far from perfect, and I need more precision.
I am looking for something similar to boundary function, but to work from the inside of the point cloud, not from the outside.
Final goal is to calculate the area between the lines on the plot.
I would do it differently. Just take any two lines of the plot, calculate the area under the curves with some kind of numerical approximation (for example trapezoidal numerical integration), then subtract the areas and obtain the area between the lines.
Thank to idea in Trilarion's answer, I was able to come up with the better solution.
Note that I use notation for YZ plane instead of XY (to keep consistent with robot coordinate system).
Solution
Generate curves for each set of scatter data
% Scatter data is in iy and iz vectors.
curve = fit(iy, iz, 'smoothingspline', 'SmoothingParam', 0.5);
% Remove outliers.
fdata = feval(curve, iy);
I = abs(fdata - iz) > 0.5 * std(iz);
outliers = excludedata(iy, iz, 'indices', I);
% Final curve without outliers.
curve = fit(iy, iz, 'smoothingspline', 'Exclude', outliers, 'SmoothingParam', 0.5);
Plot curves and scatter data
% Color maps generated by MATLAB's colormap function.
h_curve = plot(curve);
set(h_curve, 'Color', color_map_light(i,:));
scatter(iy, iz, '.', 'MarkerFaceColor', color_map(i,:))
Let user provide an input by selecting points
User selects one point as a query point and two points for limits along Y axis. This is because some curves come close, but never intersect.
[cs_position.y, cs_position.z] = ginput(1);
[cs_area_limits, ~] = ginput(2);
if cs_area_limits(1) > cs_area_limits(2)
cs_area_limits = flipud(cs_area_limits);
end
plot_cross_section(cs_position);
Finally calculate and plot surface area
This section uses fantastic answer by Doresoom.
function [ ] = plot_cross_section(query_point)
%PLOT_CROSS_SECTION Calculates and plots cross-section area.
% query_point Query point.
% Find values on query point's Y on each of the curves.
z_values = cellfun(#(x, y) feval(x, y),...
curves, num2cell(ones(size(curves)) * query_point.y))
% Find which curves are right above and below the query point.
id_top = find(z_values >= query_point.z, 1, 'first')
id_bottom = find(z_values < query_point.z, 1, 'last')
if isempty(id_top) || isempty(id_bottom)
return
end
% Generate points along curves on the range over Y.
y_range = cs_area_limits(1):0.1:cs_area_limits(2);
z_top = feval(curves{id_top}, y_range).';
z_bottom = feval(curves{id_bottom}, y_range).';
% Plot area.
Y = [ y_range, fliplr(y_range) ];
Z = [ z_top, fliplr(z_bottom) ];
fill(Y, Z, 'b', 'LineStyle', 'none')
alpha 0.5
hold on
% Calculate area and show to user.
cs_area = polyarea(Y, Z);
area_string = sprintf('%.2f mm^2', cs_area);
text(0, -3, area_string, 'HorizontalAlignment', 'center')
end
Result
I want a plot as the following:
Here, the Wigner function calculated from the x,y data is plotted as W and its projection on the x-y plane is also shown.
I have used the following code that plots the Wigner function. How to show the projection of W on the x-y plane in the same plot?
xvec = [-2:2];
yvec = xvec;
W = wfunc(psi,xvec,yvec,g);
f1 = figure(1);
mesh(xvec,yvec,real(W));
shading interp
You can use hold on to add many graphical objects in the same figure. For example:
figure
surf(xvec,yvec,real(W),'linestyle','none')
hold on
contourf(xvec,yvec,real(W),100,'linestyle','none')
You can shift the z-position of the contour colormap (following to the comment here) using
[~,hc] = contourf(xvec,yvec,real(W),100,'linestyle','none');
hcpatches = findobj(hc,'Type','Patch');
for n=1:length(hcpatches)
set(hcpatches(n),'ZData',-5*ones(size(get(hcpatches(n),'XData'))))
end
Also, you can try to use surfc.
I tried generating the cone of influence for a Morlet wavelet power spectrum using the following MATLAB code:
cone = conofinf('morl',1:365,LenSig,[],'plot');
However, all I get is a strange looking shaded area bounded by two linear lines. It doesn't look like a cone of influence for Morlet wavelet power spectrum.
What did I do wrong?
I guess you wanted to output COI at the borders of your wavelet transform. In this case you have to specify the last parameter as non-empty vector, but with coordinates, where you need COI to be computed, e.g.
cone = conofinf('morl',1:365,LenSig,[1 LenSig],'plot');
I had a similar task and here's what I did:
figure;
% plot wavelet transform / scalogram
imagesc(t,scales,WT);
axis square;
colorbar;
% annotate axes and title
title('Coefficients of continuous wavelet transform');
xlabel('Time (or space) b');
ylabel('Scales a');
% get cone of influence
% Here, you have to specify points at which you want to calculate COI
% as the last parameter:
cone = conofinf(wname,scales,LenSig,[1 LenSig]);
% combine left and right edges
cone = [cone{1}(:,floor(1:LenSig/2)) cone{2}(:,ceil(LenSig/2):end)];
% previous steps give you an area under COI
% you can see it with: figure; imagesc(cone);
% now, we want to get the border of this area
coi = zeros(1,LenSig);
for idx = 1:LenSig
valcoi = find(cone(:,idx)==1,1,'last');
if ~isempty(valcoi)
coi(idx) = f(valcoi);
end
end
% now plot COI border on top of your wavelet transform
hold on;
plot(t,coi,'k','LineWidth',1.5);
hold off;
Optionally, you can hatch the area under COI, but it's a bit of a hack and it's not ideal. For this you will need hatchfill function (here's an example how to use it). Once you have this function on your path, you can use it like this:
[~,h] = contourf(t,scales,cone*max(WT(:)),[1 1]*max(WT(:)));
hPatch = findobj(h, 'Type', 'patch');
hh = hatchfill(hPatch, 'cross', 45, 10);
i have four points with that i made a polygon using matlab
x = [2271 -3645 -2267 3645];
y = [-3635 -2259 3639 2254];
figure;
plot([x x(1)],[y y(1)],'r-');
i got a polygon, i need to generate the grid above the rectangle with 50*50 interval
i made a try with zgrid function , but its not giving the result.
i need a 2D grid on that polygon, i need to take the grid points into a file.
please help me to solve this
thanks in advance
To generate a point grid confined to the interior of your polygon you can do the following:
[X,Y]=meshgrid(linspace(min(x),max(x),round((max(x)-min(x))/50)),linspace(min(y),max(y),round((max(y)-min(y))/50)));
isin=inpolygon(X(:),Y(:),[x x(1)],[y y(1)]);
Xin = X(isin);
Yin = Y(isin);
Here [Xin, Yin] contains the coordinates of the grid vertices.
You can compute a grid with the meshgrid matlab's built-in function, and draw it with mesh for example. The mesh coordinates are stored in X and Y.
Here the polygon you defined is plotted on the top of the grid. The following code
x = [2271 -3645 -2267 3645];
y = [-3635 -2259 3639 2254];
outside = 100;
grid_val = 50;
figure('Color','w');
[X,Y] = meshgrid(min(x)-outside:grid_val:max(x)+outside, min(y)-outside:grid_val:max(y)+outside);
hold on;
hm = mesh(X,Y,X*0);
hp = plot([x x(1)],[y y(1)],'r-');
set(hm,'EdgeColor','k')
set(hp,'LineWidth',2)
set(gca,'Visible','off');
gives the following grid (full and zoom)