Drawing and filling different polygons at the same time in MATLAB - matlab

I have the code below. It load a CSV file into memory. This file contains the coordinates for different polygons.Each row of this file has X,Y coordinates and a string which tells that to which polygon this datapoint belongs. for example a polygone named "Poly1" with 100 data points has 100 rows in this file like :
Poly1,X1,Y1
Poly1,X2,Y2
...
Poly1,X100,Y100
Poly2,X1,Y1
.....
The index.csv file has the number of datapoint(number of rows) for each polygon in file Polygons.csv. These details are not important. The thing is:
I can successfully extract the datapoints for each polygon using the code below.
However, When I plot the lines of different polygons are connected to each other and the plot looks crappy. I need the polygons to be separated(they are connected and overlapping the some areas though). I thought by using "fill" I can actually see them better. But "fill" just filles every polygon that it can find and that is not desirable. I only want to fill inside the polygons. Can someone help me? I can also send you my datapoint if necessary, they are less than 200Kb.
Thanks
[coordinates,routeNames,polygonData] = xlsread('Polygons.csv');
index = dlmread('Index.csv');
firstPointer = 0
lastPointer = index(1)
for Counter=2:size(index)
firstPointer = firstPointer + index(Counter) + 1
hold on
plot(coordinates(firstPointer:lastPointer,2),coordinates(firstPointer:lastPointer,1),'r-')
lastPointer = lastPointer + index(Counter)
end

This solution may work for you:
[coordinates,routeNames,polygonData] = xlsread('Polygons.csv'); %# Load the data
for polyName = unique(routeNames(:).') %'# Loop over unique polygons
polyIndex = ismember(routeNames,polyName); %# Find index of polygon points
x = coordinates(polyIndex,:); %# Get x coordinates
y = coordinates(polyIndex,:); %# Get y coordinates
patch(x,y); %# Plot a patch
hold on; %# Add to the existing plot
end
This creates the polygons using the PATCH function. To color the patches differently, check out this MATLAB documentation.

I think patch is a better tool for drawing filled polygons. Check it out!

Related

Smooth edge contour plot

Hello
I want to represent data with 2 variables (latitude and longitude) in 2D format. The value is represented by color and the 2 variables as the 2 axis and I am using the contourf function to plot my data. All the data comes from a xlsx file and I put it in a matrix.
Locations = xlsread('Availability results.xlsx');
column_numberloc = 1; % Column in the locations file containing the number of the locations
column_latitude = 2; % Column in the locations file containing the latitude of the locations
column_longitude = 3; % Column in the locations file containing the longitude of the locations
column_availability = 4; % Column in the locations file containing the availability of the locations
min_latitude = min(Locations(:,column_latitude));
max_latitude = max(Locations(:,column_latitude));
min_longitude = min(Locations(:,column_longitude));
max_longitude = max(Locations(:,column_longitude));
max_availability = max(Locations(:,column_availability));
min_availability = min(Locations(:,column_availability));
longitude = Locations(:,column_longitude);
latitude = Locations(:,column_latitude);
Contour = zeros(23,17);
for numerofile=1:204
[coord_x,coord_y] =transformation(Locations(numerofile,column_latitude),Locations(numerofile,column_longitude));
Contour(coord_x,coord_y) = Locations(numerofile,column_availability);
end
for i=1:23
for j=1:17
if Contour(i,j) == 0
Contour(i,j) = NaN;
end
end
end
cMap=jet(256);
figure(1);
x = linspace(min_longitude,max_longitude,17);
y = linspace(min_latitude,max_latitude,23);
newpoints = 100;
[xq,yq] = meshgrid(linspace(min(x),max(x),newpoints),linspace(min(y),max(y),newpoints ));
Contourq = interp2(x,y,Contour,xq,yq,'linear',max_availability);
[c,h]=contourf(xq,yq,Contourq,100);
%[c,h]=contourf(x,y,Contour,50);
set(h, 'edgecolor','none');
colormap(cMap);
cb=colorbar;
caxis([min_availability max_availability]);
The transformation function allows me to place all the data in the Contour matrix as it associate a longitude and a latitude to a row and a column.
I've putted a NaN for every data equal to zero to have a better look at my data and I obtained this :
interpolation_linear
Which is nice but I wanted this data to be close to :
Without interpolation
So, I decided to change the linear interpolation to a 'nearest' interpolation and I got this :
interpolation_nearest
I can see more data but the contour plot isn't as smooth as with the linear interpolation.
I've seen many posts about how to make smooth contour plot (that's how I found the function 'interp2') but I think that my problem comes from the NaN data which prevent me from having a smooth contour plot at the edge between NaN values and the rest like the first image but with enough data like the third image.
My question is : Do you know how can I get a smooth edge contour plot with enough data thanks to the nearest interpolation but with a nice visual like the first image ?
Thank you very much
Since you are doing an interpolation on a square grid, you could directly display a 2D image with imagesc.
The advantage is that you can access the AlphaData property of image objects, which can be used as a display mask.
r=rand(50); % random 50x50 array
r(11:20,11:20)=NaN; % some hole filled with NaN
imagesc(r) % show the image, with NaN considered as the lowest value in color scale
imagesc(r,'AlphaData',~isnan(r)) % show the image, with NaN values set as fully transparent
You may also then:
set a display mask first
replace zeros or NaN with some meaningful values (nearest non NaN value?)
interpolate with interp2, perhaps even with the 'cubic' parameter for improved smoothness
display only the meaningful part of the image thanks to the display mask set in AlphaData.

multiple matlab contour plots with one level

I have a number of 2d probability mass functions from 2 categories. I am trying to plot the contours to visualise them (for example at their half height, but doesn't really matter).
I don't want to use contourf to plot directly because I want to control the fill colour and opacity. So I am using contourc to generate xy coordinates, and am then using fill with these xy coordinates.
The problem is that the xy coordinates from the contourc function have strange numbers in them which cause the following strange vertices to be plotted.
At first I thought it was the odd contourmatrix format, but I don't think it is this as I am only asking for one value from contourc. For example...
contourmatrix = contourc(x, y, Z, [val, val]);
h = fill(contourmatrix(1,:), contourmatrix(2,:), 'r');
Does anyone know why the contourmatrix has these odd values in them when I am only asking for one contour?
UPDATE:
My problem seems might be a failure mode of contourc when the input 2D matrix is not 'smooth'. My source data is a large set of (x,y) points. Then I create a 2D matrix with some hist2d function. But when this is noisy the problem is exaggerated...
But when I use a 2d kernel density function to result in a much smoother 2D function, the problem is lessened...
The full process is
a) I have a set of (x,y) points which form samples from a distribution
b) I convert this into a 2D pmf
c) create a contourmatrix using contourc
d) plot using fill
Your graphic glitches are because of the way you use the data from the ContourMatrix. Even if you specify only one isolevel, this can result in several distinct filled area. So the ContourMatrix may contain data for several shapes.
simple example:
isolevel = 2 ;
[X,Y,Z] = peaks ;
[C,h] = contourf(X,Y,Z,[isolevel,isolevel]);
Produces:
Note that even if you specified only one isolevel to be drawn, this will result in 2 patches (2 shapes). Each has its own definition but they are both embedded in the ContourMatrix, so you have to parse it if you want to extract each shape coordinates individually.
To prove the point, if I simply throw the full contour matrix to the patch function (the fill function will create patch objects anyway so I prefer to use the low level function when practical). I get the same glitch lines as you do:
xc = X(1,:) ;
yc = Y(:,1) ;
c = contourc(xc,yc,Z,[isolevel,isolevel]);
hold on
hp = patch(c(1,1:end),c(2,1:end),'r','LineWidth',2) ;
produces the same kind of glitches that you have:
Now if you properly extract each shape coordinates without including the definition column, you get the proper shapes. The example below is one way to extract and draw each shape for inspiration but they are many ways to do it differently. You can certainly compact the code a lot but here I detailed the operations for clarity.
The key is to read and understand how the ContourMatrix is build.
parsed = false ;
iShape = 1 ;
while ~parsed
%// get coordinates for each isolevel profile
level = c(1,1) ; %// current isolevel
nPoints = c(2,1) ; %// number of coordinate points for this shape
idx = 2:nPoints+1 ; %// prepare the column indices of this shape coordinates
xp = c(1,idx) ; %// retrieve shape x-values
yp = c(2,idx) ; %// retrieve shape y-values
hp(iShape) = patch(xp,yp,'y','FaceAlpha',0.5) ; %// generate path object and save handle for future shape control.
if size(c,2) > (nPoints+1)
%// There is another shape to draw
c(:,1:nPoints+1) = [] ; %// remove processed points from the contour matrix
iShape = iShape+1 ; %// increment shape counter
else
%// we are done => exit while loop
parsed = true ;
end
end
grid on
This will produce:

Matlab Shape Labelling

I have a set of shapes in an image I would like to label according to their area, I have used bwboundaries to find them, and regionprops to determine their area. I would like to label them such that they are labelled different based on whether their area is above or below the threshold i have determined.
I've thought about using inserObjectAnnotation, but I'm not sure how to add on a condition based on their area into the function?
Assuming TH to be the threshold area and BW to be the binary image and if you are okay with labeling them as o's and x's with matlab figure text at their centers (centroids to be exact), based on the thresholding, see if this satisfies your needs -
stats = regionprops(BW,'Area')
stats2 = regionprops(BW,'Centroid')
figure,imshow(BW)
for k = 1:numel(stats)
xy = stats2(k).Centroid
if (stats(k).Area>TH)
text(xy(1),xy(2),'L') %// Large Shape
else
text(xy(1),xy(2),'S') %// Small Shape
end
end
Sample output -
You could use CC = bwconncomp(BW,conn).
To get the number of pixels of every connected compontent you can use:
numPixels = cellfun(#numel,CC.PixelIdxList);
In CC.PixelIdxList you have a list of all found objects and the indices of the pixels belonging to the components. I guess to label your areas you could do something like:
for ind = 1:size(CC.PixelIdxList,2)
Image(CC.PixelIdxList{ind}) = ind;
end

Computing distance between between 2 point of a 3D figure using datacursor

I am building a GUI that plot a 3D figure by pressing button. I am trying to return a distance value between 2 points when I select the 2 points using datacursormode on the figure. I know the formula to calculate the distance, but I don't know how to make the data cursor return the (X,Y,Z) value of the 2 points selected.
Thanks.
%// retrieve the data cursor manager for the figure
dcm = datacursormode(gcf) ;
%// get all the datatips information in a structure
dtip_info = dcm.getCursorInfo ;
%// extract the coordinates of each data tip from the structure
Coordinates_Datatip1 = dtip_info(1).Position ;
Coordinates_Datatip2 = dtip_info(2).Position ;
This assume you already have 2 datatips in the current figure.
Each "Coordinates_Datatip" variable will contain 3 scalar values x,y and z position of your datatips.

Creating a movie in MATLAB with point data for a simple N-body simulation

I am trying to write a simple n-body gravity simulation with 4 particles in C++. I am outputting the positions of the 4 particles to .mat files labeled "time_X.mat" (where X=1,2,3.... indicates the time-stamp) in the form of a 4x2 matrix where
i'th row indicates (x,y) cooridinates of the ith particle at time X .
Now for a particular time-step I am able load the .mat file into MATLAB and get a scatterplot of the points in the matrix, showing me particle positions. But I would like to create a movie out of all the .mat files / scatter-plots of the time_X.mat files which shows me the evolution of the 4 particle syestem . How should I do that in MATLAB?
First you have to make frames (images) of each time step of your simulation.
Since you have Cartesian coordinates, you have to convert your x and y coordinates to pixel indices, and make an image matrix from them. See my answer to a relevant question for an example of how to do this. You could also modify the code to make your points larger than a pixel, have shapes, etc., perhaps with strel or [a,b,~] = sphere(N).
Once you have the frames, you can easily make an AVI file (uncompressed or MPEG) in MATLAB:
aviOutput = fullfile('path','to','file.avi');
aviobj = VideoWriter(aviOutput);
aviobj.Quality = 100;
aviobj.FrameRate = 24; %# arbitrary
open(aviobj);
for i=1:length(frames)
writeVideo(aviobj,frames{i}); %# or frames(:,:,i) etc.
end
close(aviobj);
Update
The above assumes the time steps are all available. For example:
files = dir('path/to/dir');
files(1:2) = []; %# . and ..
orderedfiles = cell(length(files),1);
for i=1:length(files)
ind = sscanf(files(i).name,[name '%*[_]%u%*s']);
orderedfiles{ind+1} = files(i).name;
end
timeSteps = zeros(numPoints,2,length(orderedfiles));
for i=1:length(orderedfiles)
temp = load(orderedfiles(i).name);
timeSteps(:,:,i) = temp.matrixName %# All the same name?
end
The code from the linked answer is written to operate on two vectors x and y with the coordinates, which you would get with timeSteps(:,1,i) and timeSteps(:,2,i), and do for each time step.