selective direction for voronoi diagram in matlab - matlab

How can I create a voronoi diagram on these squares in MATLAB, as the voronoi does not enter the yellow square? Alternatively, just some lines of it enters the yellow ones.

It is possible to put constrains on Delaunay triangulation, and add more checks afterwards. maybe it can help you:
close all
% generate random rectangels [x,y,w,h] format
n = 8;
w = 0.15;
h = 0.05;
rects = [rand(n,2),w*ones(n,1),h*ones(n,1)];
% convert to [xmin ymin xmax ymax] format
boxes = [rects(:,1:2), rects(:,1:2) + rects(:,3:4)];
% convert to one single polygon (with missing vertexes)
X = boxes(:,[1 3 3 1 1]);
Y = boxes(:,[2 2 4 4 2]);
X(:,end+1) = nan;
Y(:,end+1) = nan;
X = X';X = X(:);
Y = Y';Y = Y(:);
% polygon vertxes without the Nans
XX = X;XX(6:6:end) = [];
YY = Y;YY(6:6:end) = [];
% intersections between rectangles
[xi,yi] = polyxpoly(X,Y,X,Y,'unique');
% remove intersections found inside rectangles
IN = any(bsxfun(#gt,xi',boxes(:,1)) & bsxfun(#lt,xi',boxes(:,3)) & ...
bsxfun(#gt,yi',boxes(:,2)) & bsxfun(#lt,yi',boxes(:,4)),1);
xi(IN) = [];
yi(IN) = [];
% find vertex pairs of the rectangles
xeq = bsxfun(#eq,xi,xi');
yeq = bsxfun(#eq,yi,yi');
xyeq = triu(xeq | yeq,1);
[idx1,idx2] = find(xyeq);
% generate constrains for the triangulation
C = [idx1,idx2];
% triangulate
DT = delaunayTriangulation([xi,yi],C);
% get connections (triangles) list
TRI = DT.ConnectivityList;
remIdx = false(size(TRI,1),1);
% check condition to remove triangles
for ii = 1:size(TRI,1)
% current triangle coordinates
xx = xi(TRI(ii,[1:3 1]));
yy = yi(TRI(ii,[1:3 1]));
% find if triangle inside rectangle
BETx = bsxfun(#ge,xx(1:3)',boxes(:,1)) & bsxfun(#le,xx(1:3)',boxes(:,3));
BETy = bsxfun(#ge,yy(1:3)',boxes(:,2)) & bsxfun(#le,yy(1:3)',boxes(:,4));
IN = BETx & BETy;
if any(all(IN,2))
remIdx(ii) = true;
continue;
end
% find if triangle crosses rectangle
[xxi,yyi] = polyxpoly(xx,yy,X,Y,'unique');
notAllowedVertex = ~ismember([xxi yyi],[xi,yi],'rows');
if any(notAllowedVertex)
remIdx(ii) = true;
continue;
end
end
% remove unwanted triangles
TRI(remIdx,:) = [];
% plot
figure;
hold on
plot(X,Y,'g','LineWidth',2)
triplot(TRI,xi,yi)
plot(xi,yi,'or')
axis equal

Related

How do I label lines in a MatLab plot?

What my plot looks like
What the plot should look like
The code is working like it should but im trying to get the labels to show up on each line from (1-8). Just like the picture above.
I have read a bunch of posts and tried to search Matlab but i havent been able to figure it out.
clc;clear;close all;
V_inf = 20; % freestream velocity
R = 1; % cylinder radius
n = 8; % number of panels
d_theta = 2*pi/n; % resolution of angles
alpha = 0; % angle of attack
theta = pi+pi/n:-d_theta:-pi+pi/n; % angles of boundary points of panels
X = R*cos(theta); % X coordinates of boundary points of panels
Y = R*sin(theta); % Y coordinates of boundary points of panels
Phi = zeros(n,1); % angle from Vinf to bottom of panel
beta = zeros(n,1); % angle from Vinf to outward normal of panel
conX = zeros(n,1); % X coordinates of control points
conY = zeros(n,1); % Y coordinates of control points
S = zeros(n,1); % panel length
for i = 1:n
Phi(i) = -alpha + atan2((Y(i+1)-Y(i)),(X(i+1)-X(i)));
beta(i) = Phi(i)+pi/2;
if beta(i)>2*pi, beta(i)=beta(i)-2*pi;
elseif beta(i)<0, beta(i)=beta(i)+2*pi; end
conX(i) = (X(i+1)+X(i))/2;
conY(i) = (Y(i+1)+Y(i))/2;
S(i) = sqrt((X(i+1)-X(i))^2 + (Y(i+1)-Y(i))^2);
end
close all
plot(R*cos(0:0.01:2*pi),R*sin(0:0.01:2*pi),'b', X,Y,'r',conX,conY,'g^');
axis equal; legend('Exact shape','Panel approximation','Control points')
xlabel('x, m'); ylabel('y, m'); title('Fig. 1 Panel layout (n = 8, R = 1m)');
Possibly plotting the labels along the points of a circle using the text() function may suffice. There's some shifting of points and flipping that needs to be done to get the order you wish but otherwise it's just 8 points taken along a circle that is smaller in diameter in comparison to the octagon. An alternative would be using the green triangles as reference instead but that involves more math. As long as your octagon is expected to be symmetrical vertically and horizontally this should work alright.
clc;clear;close all;
V_inf = 20; % freestream velocity
R = 1; % cylinder radius
n = 8; % number of panels
d_theta = 2*pi/n; % resolution of angles
alpha = 0; % angle of attack
theta = pi+pi/n:-d_theta:-pi+pi/n; % angles of boundary points of panels
X = R*cos(theta); % X coordinates of boundary points of panels
Y = R*sin(theta); % Y coordinates of boundary points of panels
Phi = zeros(n,1); % angle from Vinf to bottom of panel
beta = zeros(n,1); % angle from Vinf to outward normal of panel
conX = zeros(n,1); % X coordinates of control points
conY = zeros(n,1); % Y coordinates of control points
S = zeros(n,1); % panel length
for i = 1:n
Phi(i) = -alpha + atan2((Y(i+1)-Y(i)),(X(i+1)-X(i)));
beta(i) = Phi(i)+pi/2;
if beta(i)>2*pi, beta(i)=beta(i)-2*pi;
elseif beta(i)<0, beta(i)=beta(i)+2*pi; end
conX(i) = (X(i+1)+X(i))/2;
conY(i) = (Y(i+1)+Y(i))/2;
S(i) = sqrt((X(i+1)-X(i))^2 + (Y(i+1)-Y(i))^2);
end
close all
plot(R*cos(0:0.01:2*pi),R*sin(0:0.01:2*pi),'b', X,Y,'r',conX,conY,'g^');
axis equal; legend('Exact shape','Panel approximation','Control points')
xlabel('x, m'); ylabel('y, m'); title('Fig. 1 Panel layout (n = 8, R = 1m)');
%*************************************************************************%
%ADDING LABELS BY PLOTTING LABELS ALONG CIRCLE%
%*************************************************************************%
Radius = 0.8;
Number_Of_Data_Points = 9;
theta = linspace(0,2*pi,Number_Of_Data_Points);
X_Circle = Radius*cos(theta);
X_Circle = X_Circle(1:end-1);
Y_Circle = Radius*sin(theta);
Y_Circle = Y_Circle(1:end-1);
X_Circle = flip(circshift(X_Circle,3));
Y_Circle = flip(circshift(Y_Circle,3));
for Point_Index = 1: numel(conX)
X_Displacement = X_Circle(Point_Index);
Y_Displacement = Y_Circle(Point_Index);
text(X_Displacement,Y_Displacement,num2str(Point_Index),'HorizontalAlignment','center','fontsize',20);
end
To Plot on Control Points:
%*************************************************************************%
%ADDING LABELS BY PLOTTING LABELS ALONG CONTROL POINTS%
%*************************************************************************%
for Point_Index = 1: numel(conX)
text(conX(Point_Index),conY(Point_Index),num2str(Point_Index),'HorizontalAlignment','center','fontsize',20);
end

Ordered Isoline Calculation from 3D Triangular Surface in MATLAB

I need to extract the isoline coordinates of a 4D variable from a 3D surface defined using a triangulated mesh in MATLAB. I need the isoline coordinates to be a ordered in such a manner that if they were followed in order they would trace the path i.e. the order of the points a 3D printer would follow.
I have found a function that can calculate the coordinates of these isolines (see Isoline function here) but the problem is this function does not consider the isolines to be joined in the correct order and is instead a series of 2 points separated by a Nan value. This makes this function only suitable for visualisation purposes and not the path to follow.
Here is a MWE of the problem of a simplified problem, the surface I'm applying it too is much more complex and I cannot share it. Where x, y and z are nodes, with TRI providing the element connectivity list and v is the variable of which I want the isolines extracted from and is not equal to z.
If anyone has any idea on either.....
A function to extract isoline values in the correct order for a 3D tri mesh.
How to sort the data given by the function Isoline so that they are in the correct order.
.... it would be very much appreciated.
Here is the MWE,
% Create coordinates
[x y] = meshgrid( -10:0.5:10, -10:0.5:10 );
z = (x.^2 + y.^2)/20; % Z height
v = x+y; % 4th dimension value
% Reshape coordinates into list to be converted to tri mesh
x = reshape(x,[],1); y = reshape(y,[],1); z = reshape(z,[],1); v = reshape(v,[],1);
TRI = delaunay(x,y); % Convertion to a tri mesh
% This function calculates the isoline coordinates
[xTows, yTows, zTows] = IsoLine( {TRI,[x, y, z]}, v, -18:2:18);
% Plotting
figure(1); clf(1)
subplot(1,2,1)
trisurf(TRI,x,y,z,v)
hold on
for i = 1:size(xTows,1)
plot3( xTows{i,1}, yTows{i,1}, zTows{i,1}, '-k')
end
hold off
shading interp
xlabel('x'); ylabel('y'); zlabel('z'); title('Isolines'), axis equal
%% This section is solely to show that the isolines are not in order
for i = 1:size(xTows,1)
% Arranging data into colums and getting rid of Nans that appear
xb = xTows{i,1}; yb = yTows{i,1}; zb = zTows{i,1};
xb = reshape(xb, 3, [])'; xb(:,3) = [];
yb = reshape(yb, 3, [])'; yb(:,3) = [];
zb = reshape(zb, 3, [])'; zb(:,3) = [];
subplot(1,2,2)
trisurf(TRI,x,y,z,v)
shading interp
view(2)
xlabel('x'); ylabel('y'); zlabel('z'); title('Plotting Isolines in Order')
axis equal; axis tight; hold on
for i = 1:size(xb,1)
plot3( [xb(i,1) xb(i,2)], [yb(i,1) yb(i,2)], [zb(i,1) zb(i,2)], '-k')
drawnow
end
end
and here is the function Isoline, which I have slightly adpated.
function [xTows, yTows, zTows] = IsoLine(Surf,F,V,Col)
if length(Surf)==3 % convert mesh to triangulation
P = [Surf{1}(:) Surf{2}(:) Surf{3}(:)];
Surf{1}(end,:) = 1i;
Surf{1}(:,end) = 1i;
i = find(~imag(Surf{1}(:)));
n = size(Surf{1},1);
T = [i i+1 i+n; i+1 i+n+1 i+n];
else
T = Surf{1};
P = Surf{2};
end
f = F(T(:));
if nargin==2
V = linspace(min(f),max(f),22);
V = V(2:end-1);
elseif numel(V)==1
V = linspace(min(f),max(f),V+2);
V = V(2:end-1);
end
if nargin<4
Col = 'k';
end
H = NaN + V(:);
q = [1:3 1:3];
% -------------------------------------------------------------------------
% Loop over iso-values ----------------------------------------------------
xTows = [];
yTows = [];
zTows = [];
for k = 1:numel(V)
R = {[],[]};
G = F(T) - V(k);
C = 1./(1-G./G(:,[2 3 1]));
f = unique(T(~isfinite(C))); % remove degeneracies by random perturbation
F(f) = F(f).*(1+1e-12*rand(size(F(f)))) + 1e-12*rand(size(F(f)));
G = F(T) - V(k);
C = 1./(1-G./G(:,[2 3 1]));
C(C<0|C>1) = -1;
% process active triangles
for i = 1:3
f = any(C>=0,2) & C(:,i)<0;
for j = i+1:i+2
w = C(f,q([j j j]));
R{j-i} = [R{j-i}; w.*P(T(f,q(j)),:)+(1-w).*P(T(f,q(j+1)),:)];
end
end
% define isoline
for i = 1:3
X{i} = [R{1}(:,i) R{2}(:,i) nan+R{1}(:,i)]';
% X{i} = [R{1}(:,i) R{2}(:,i)]'; % Changed by Matt
X{i} = X{i}(:)';
end
% plot isoline
if ~isempty(R{1})
% hold on
% H(k) = plot3(X{1},X{2},X{3},Col);
% Added by M.Thomas
xTows{k,1} = X{1};
yTows{k,1} = X{2};
zTows{k,1} = X{3};
end
end
What you will notice is that the isolines (xTows, yTows and zTows) are not in order there "jump around" when plotted sequentially. I need to sort the tows so that they give a smooth plot in order.

Create a plane of points from a row of points

I am trying to create a "plane", so to speak, of points in MATLAB from a set of initial points. I have so far been able to create only one row of points, with the algorithm shown below:
% Generate molecular orientation and position
a = 4.309; % lattice constant in angstroms
l = 10; % number of lattices desired
placeHolder = [0 0 0 ; a/2 a/2 0; a/2 0 a/2; 0 a/2 a/2]; % centers of molecules
numMol = 4; %input('how many molecules are in the unit cell? \n # molecules = ');
numAtoms = 2; %input('how many atoms per molecule? \n # atoms per molecule = ');
atomPerUC = numMol*numAtoms; % number of atoms per unit cell
dir = zeros(numMol,3); % array for orientations
atomPosition = zeros(numAtoms*l^3,3,numMol); % array for positions of atoms
theta = zeros(numMol,1); % array for theta values
phi = zeros(numMol,1); % array for phi values
b = 1.54; % bond length in angstroms
for kk = 1:numMol % generate unit cell
% disp(['What is the molecular orientation for molecule ',num2str(kk),' ?']);
% dir(kk,1) = input('u = '); % ask for user input for molecular orientations
% dir(kk,2) = input('v = ');
% dir(kk,3) = input('w = ');
dir = [1,1,1;-1,1,1;-1,-1,1;1,-1,1];
u = dir(kk,1); % set variables for theta, phi computation
v = dir(kk,2);
w = dir(kk,3);
theta(kk) = w/sqrt(u^2+v^2+w^2); % theta value for molecule k
if v<0 % phi value for molecule k
phi(kk) = 2*pi - acos(abs(v)/sqrt(u^2+v^2+w^2));
else if v>0
phi(kk) = acos(u/sqrt(u^2+v^2+w^2));
end
end
theta = theta(kk); phi = phi(kk); % set variables for theta, phi for x,y,z computation
xp = placeHolder(kk,1); % cooridnates of center of molecule k
yp = placeHolder(kk,2);
zp = placeHolder(kk,3);
x1 = (b/2)*sin(theta)*cos(phi) + xp; % cooridnates for atoms in molecule
x2 = -(b/2)*sin(theta)*cos(phi) + xp;
y1 = (b/2)*sin(theta)*sin(phi) + yp;
y2 = -(b/2)*sin(theta)*sin(phi) + yp;
z1 = (b/2)*cos(theta) + zp;
z2 = -(b/2)*cos(theta) + zp;
atomPosition(1,:,kk) = [x1 y1 z1];
atomPosition(2,:,kk) = [x2 y2 z2];
end
for k = 1:numMol
x01 = atomPosition(1,1,k); y01 = atomPosition(1,2,k); z01 = atomPosition(1,3,k);
x02 = atomPosition(2,1,k); y02 = atomPosition(2,2,k); z02 = atomPosition(2,3,k);
for ii = 1:l-1
atomPosition(2*ii+1,:,k) = [(atomPosition(2*ii-1,1,k) + a) y01 z01];
atomPosition(2*ii+2,:,k) = [(atomPosition(2*ii,1,k) + a) y02 z02];
end
end
My problem is that I do not know how to, from here, turn this "row" of points into a "plane" of points. This can be thought of as taking the points that are known on the x-axis, and creating similar rows moving up in the y-direction to create an x-y plane of points.
Any help/suggestions would be appreciated!
Though I do not understand exactly what you are trying to do. In a simple case you can move from a row of points to a plane by adding the extra dimension.
ie.
x=[1,2,3,4,5]
y=x^2
changes to
x=[1,2,3,4,5]
y=[1,2,3,4,5]
[x,y] = meshgrid(x,y)
z=x^2+y^2

Displaying surf actual size?

Is there a way to display surf in its actual size and aspect ratio? I've been looking in the web but couldn't find anything which worked. I'm also quite new to MATLAB.
Here is my code:
rpos1 = 0; % image row vector pos counter
rpos2 = 0; % existing image vector pos counter
rpos3 = 0; % avg vector pos counter
prompt = {'Image location:','Lowest image #:','Highest image #:','Row of interest:','Background noise reduction:'};
dlg_title = 'Input';
num_lines = 1;
def = {'C:\Users\Moz\Desktop\Hyperspecdata\images','300','390','700','100'};
answer = inputdlg(prompt,dlg_title,num_lines,def);
directory = (answer{1});
x1 = str2num(answer{2});
x2 = x1;
y1 = str2num(answer{3});
y2 = y1-1;
z = str2num(answer{4});
v = str2num(answer{5});
finalslice = zeros(1,1312); % create matrix (imagecount x 1312)
%INSERT SLICES WITH 1 GAP%
for k = x1 : y1
baseFileName = sprintf('image0000000%03d.pgm',k);
fullFileName = fullfile(directory, baseFileName); %fullfile(folder, baseFileName);
A = imread(fullFileName);
A = floor(A./16); % transform back to 12 bit
B = A-v; % remove background noise
rpos1 = rpos1+1; % jump to next row
thisline = B(z,:); % desired row in images
finalslice(rpos1,:) = thisline; % add row vector
rpos1 = rpos1+1; % jump to next row
emptyline = zeros(1,1312); % create empty row vector
finalslice(rpos1,:) = emptyline; % insert empty row vector
end
%INSERT AVERAGES INTO GAPS%
for k = x2 : y2
rpos2 = rpos2+1; % find first existing vector
line1 = finalslice(rpos2,:);
rpos2 = rpos2+2; % find second existing vector
line2 = finalslice(rpos2,:);
avgline1 = (line1 + line2)/2; % average both
rpos3 = rpos3+2;
finalslice(rpos3,:) = avgline1; % insert average vector
rpos2 = rpos2-1; % jump back to second existing vector
end
figure(1)
h = surf(finalslice,'EdgeColor','none','LineStyle','none','FaceLighting','phong');
colormap('jet');
view(2)
I'm loading a bunch of images and taking slices at a specific points and stitching them together. The output doesn't display the actual size and aspect ratio.
SOLVED:
Added daspect()
o = max(max(finalslice));
[m n] = size(finalslice);
figure(1) h = surf(finalslice,'EdgeColor','none','LineStyle','none','FaceLighting','phong'); colormap('jet');
view(2)
daspect([m n o]);

How can I modify the colors on MATLAB's colorbar

I am plotting the azimuth and elevation of some satellites, where the color of each trajectory represents the S4 index, from low (blue) to high (red). I would like however, to be able to format the colors and corresponding values, so that more of the lower effects of scintillation can actually be distinguished. This is because the high end of scintillation (red) only shows one or two points. Here is a picture of the trajectory and the code.
clc; close all; clear all
load combo_323_full
circular_plot
x = [];
y = [];
for s = 1:samples
% plot each satellite location for that sample
for sv = 1:sats
% check if positive or negative elevation
if (elevation((s - 1) * sats + sv) < 0)
elNeg = 1;
else
elNeg = 0;
end
% convert to plottable cartesian coordinates
el = elevation((s - 1) * sats + sv);
az = azimuth((s - 1) * sats + sv);
x = [x;(pi/2-abs(el))/(pi/2).*cos(az-pi/2)];
y = [y;-1*(pi/2-abs(el))/(pi/2).*sin(az-pi/2)];
% check for final sample
% if (s == samples)
% plot(x,y,'r*');
% text(x,y+.07,int2str(SVs(sv)), ...
% 'horizontalalignment', ...
% 'center','color','r');
% else
% check for +/- elevation
% if (elNeg == 0)
% plot(x,y,'.','color',rgb('DarkBlue'));
% else
% plot(x,y,'g.');
% % end
% end
end
end
z = combo(:,5);
for j = 1:10
% hold on
% circular_plot
lRef = length(x);
l1 = floor(lRef*(1/100));
l2 = floor(l1*j);
x_time = x(1:l2);
y_time = y(1:l2);
zr = z(1:l2);
navConstants;
% find out from 'plotMat' if plotting satellite locations or trajectories in
% addition determine how many satellites are being tracked and how many
% samples for each satellite (# samples / satellite must always be equal)
gpsTime = combo(1,2);
i = 1;
t = gpsTime;
while ((i ~= size(combo,1)) & (t == gpsTime))
i = i + 1;
t = combo(i,2);
end
if (t == gpsTime)
sats = i;
else
sats = i - 1;
end;
samples = size(combo,1) / sats;
SVs = combo(1:sats,1);
elevation = combo(:,20).*pi/180;
azimuth = combo(:,19).*pi/180;
% initialize polar - plotting area
figure(j);
axis([-1.4 1.4 -1.1 1.1]);
axis('off');
axis(axis);
hold on;
% plot circular axis and labels
th = 0:pi/50:2*pi;
x_c = [ cos(th) .67.*cos(th) .33.*cos(th) ];
y_c = [ sin(th) .67.*sin(th) .33.*sin(th) ];
plot(x_c,y_c,'color','w');
text(1.1,0,'90','horizontalalignment','center');
text(0,1.1,'0','horizontalalignment','center');
text(-1.1,0,'270','horizontalalignment','center');
text(0,-1.1,'180','horizontalalignment','center');
% plot spoke axis and labels
th = (1:6)*2*pi/12;
x_c = [ -cos(th); cos(th) ];
y_c = [ -sin(th); sin(th) ];
plot(x_c,y_c,'color','w');
text(-.46,.93,'0','horizontalalignment','center');
text(-.30,.66,'30','horizontalalignment','center');
text(-.13,.36,'60','horizontalalignment','center');
text(.04,.07,'90','horizontalalignment','center');
scatter(x_time,y_time,3,zr)
colorbar
axis equal
end
You can make your own colormap, it's just a N by 3 matrix where the columns are the red, green and blue components respectively.
The default colormap is jet. If you type for instance
>>> jet(16)
you will get a 16 by 3 matrix and you can see how it is made.
Then use colormap(your_own_colormap) to change it.