I have written code that simulates the rolling of a triangle and gives the output as a trace plot of the three vertices and the centroid for a specified number of rotations.
I would like to turn this plot into an animation and add a circle at each of the triangle vertices to represent wheels.
Can anyone suggest an efficient method to do this?
I am looking to make an animation something like this, except in my case I am not using a ruleaux traingle and just need an animation, not something interactive:
http://demonstrations.wolfram.com/ARollingReuleauxTriangle/
close all
clear
%functions to create rigid body transform matrix---------------------------
hat = #(w) [0,-w(3),w(2); w(3),0,-w(1); -w(2),w(1),0];
rotMatrix = #(th,w) eye(3) + hat(w)*sind(th) + hat(w)*hat(w)*(1-cosd(th));
rbTrans = #(th,w,q) [rotMatrix(th,w), (eye(3) - rotMatrix(th,w))*q(1:3); 0 0 0 1];
%arguments: th=rotation angle, w=rotation axis, q=center of rotation (column vector)
nTurns=5;
degPerTurn=120; %degrees
nStepsPerTurn=1000; %resolution of each "turn". number of points
d = 5.2; %distance from centroid to a vertex
r = 4;
w = [0;0;1;0]; %rotation vector=z-axis
X0 = [0;0;0]; %initial position of centroid
%initialize vertices
v=[0;1;0];
p1 = X0 + [0;d;0];
p2 = X0 + d*rotMatrix(-120,w)*v;
p3 = X0 + d*rotMatrix(120,w)*v;
P(1,1,:) = p1;
P(2,1,:) = p2;
P(3,1,:) = p3;
P(4,1,:) = X0;
rotVertex=2;
thStep=-degPerTurn/nStepsPerTurn;
for i=1:nTurns
for j=1:nStepsPerTurn
%center of rotation
q = squeeze(P(rotVertex,end,:));
q = q + [0; -r; 0];
%transform is a rotation of 120/nSteps about z-axis centered at a
%particular vertex
g = rbTrans(thStep, w, q);
I=size(P,2)+1; %add new element by inserting to (end+1)
for k=1:size(P,1) %for each point we're following-- vertices and centroid
pt = g*[squeeze(P(k,I-1,:)); 1]; %apply transform to last existing value of this point
P(k,I,:) = pt(1:3); %and add it to the end
end
end
%vertices are numbered clockwise around the triangle
rotVertex=rotVertex-1;
if rotVertex<1
rotVertex=rotVertex+3;
end
end
%extract data from 3D array
P1=squeeze(P(1,:,:));
P2=squeeze(P(2,:,:));
P3=squeeze(P(3,:,:));
C=squeeze(P(4,:,:));
figure
plot(P1(:,1),P1(:,2),'b'),hold on
plot(P2(:,1),P2(:,2),'r')
plot(P3(:,1),P3(:,2),'g')
plot(C(:,1),C(:,2),'k')
xlabel('Horizontal Distance (inches)')
ylabel('Vertical Distance (inches)')
axis equal
legend('Vertex 1','Vertex 2','Vertex 3','Centroid', 'Location','Best')
figure
subplot(4,1,1),plot(P1(:,1),P1(:,2)),axis equal,ylabel('P1')
subplot(4,1,2),plot(P2(:,1),P2(:,2)),axis equal,ylabel('P2')
subplot(4,1,3),plot(P3(:,1),P3(:,2)),axis equal,ylabel('P3')
subplot(4,1,4),plot(C(:,1),C(:,2)),axis equal,ylabel('C')
xlabel('Horizontal Distance (inches)')
figure
plot(P3(:,1),P3(:,2),'b'),hold on
plot(C(:,1),C(:,2),'k')
axis equal
xlabel('Horizontal Distance (inches)')
ylabel('Vertical Distance (inches)')
legend('Vertex 3','Centroid', 'Location','Best')
I would encapsulate the drawing of your points in a for loop, drawing each triple of points individually then placing a pause command for a few milliseconds accompanied with a drawnow. If you want this to be an animation, I'm assuming you only want to show one triangle per "frame", and so what you can do is when you want to plot the next set of points, take the previous points and plot them as white to artificially clear them without clearing the entire frame.
Do something like this. Bear in mind I'm only targeting the code where I think is where you want the animation to occur:
figure;
for i = 1 : size(P1, 1)
if (i > 1)
plot(P1(i-1,1), P1(i-1,2), 'w.', P2(i-1,1), P2(i-1,2), 'w.', ...
P3(i-1,1), P3(i-1,2), 'w.', C(i-1,1), C(i-1,2), 'w.');
end
plot(P1(i,1), P1(i,2), 'b.', P2(i,1), P2(i,2), 'r.', ...
P3(i,1), P3(i,2), 'g.', C(i,1), C(i,2), 'k.');
axis equal;
xlabel('Horizontal Distance (inches)');
ylabel('Vertical Distance (inches)');
legend('Vertex 1','Vertex 2','Vertex 3','Centroid', 'Location','Best');
drawnow;
pause(0.1); %// Pause for 0.1 seconds
end
Related
I generate a random number between 1 and 2 as a radius for my circle. Then I plot my circle and saves it as a png. Also, several data points are generated both inside and outside the circle to make it noisy.
Then I will use Hough Transform to estimate the radius for the circle but, the number which it returns is more than 100. Although they are the same circles(I plotted to make sure).
I have tried to use polyfit function to map these two numbers but, the estimated radius seems to be smaller than the real one in some examples. After mapping It returns the same number. For example, a random radius is 1.2 and Hough estimates it 110 however it seems that it should be near 1.(Because I plot it and it is clear that is it smaller). Also, for Hough Transform I am using this code https://www.mathworks.com/matlabcentral/fileexchange/35223-circle-detection-using-hough-transforms
I tried the predefined Matlab function (imfindcircles) but it returns null for all my circles.
r1 = 1 + abs((1)*randn(1,1)); %radius of inner circle
r1 = abs(r1);
r2 = (1.2)*r1; %radius of outercircle
k = 500; %number of random numbers
% circle coordinate points
t = 0:2*pi/59:2*pi;
xv = cos(t)';
yv = sin(t)';
%%%%%%%%random points
xq = 2*randn(k,1)-1;
yq = 2*randn(k,1)-1; %distribution 1
xq1 = 2*(rand(k,1))-1; %distribution 2
yq1 = 2*(rand(k,1))-1;
in = inpolygon(xq1,yq1,r1*xv,r1*yv); %number of points inside the geometry
in1= inpolygon(xq,yq,r2*xv,r2*yv); %points inside outer circle
in2 = xor(in,in1); %points between circle
in3= inpolygon(xq1,yq1,r2*xv,r2*yv); %points inside outer circle
fig = figure(22);hold on;
% Random points
plot(xq(in2),yq(in2),'bo','MarkerFaceColor','r','MarkerSize',5,'Marker','o','MarkerEdgeColor','none');
axis equal;
plot(xq1(~in2),yq1(~in2),'bo','MarkerFaceColor','r','MarkerSize',5,'Marker','o','MarkerEdgeColor','none');
axis equal;
img= getframe(fig);
figure;
imshow(img.cdata)
hold on;
[r,c,rad] = circlefinder(img.cdata);
[m I] = max(rad);
%ploting the bigest estimated circle
angle = 2*pi*randn(k,1);
haffpointX = rad(I).*cos(angle)+ c(I);
haffpointY = rad(I).*sin(angle)+ r(I);
scatter(haffpointX,haffpointY,'g');
axis equal
I expect that for different random circles with noisy data Hough Transform estimates its circle with the number between the range of 1 and 2 so, I can use its results.
Thank you in advance
I'm trying to calculate the mean value of the pixels inside a circle. In the future this needs to be extended to 3D, but for now a 2D sollution would already help me out.
As can be seen in the image, some pixels are entirely inside the circle, but some are only partly inside the circle. The ones partly in the circle also need to contribute only partly to the mean value. The pixels are square. This will simplify the mathematics I hope.
I can calculate the distance from the pixelcorners to the central point, from this you can find the pixels enterly inside and enterly outside. The rest needs correction. But how to find this correction.
[edit] thanks to Heath Raftery the problem is solved! [/edit]
the integral of a circle with radius r
As an example: I want to know the average pixelvalue of pixels in this circle. I know it is 0.3425, since 34.25% of the circle has a value of 1 and the rest is 0.
Function to check what part of a pixel is in the circle:
function [ a ] = incirc( x,y,r )
%only handles the top right quadrant of a circle
if x<0||y<0,error('only positive x,y');end
%integral of sqrt(r^2-x^2) dx
F = #(x,r) (1/2)*(x*sqrt(r^2-x^2)+r^2*atan(x/sqrt(r^2-x^2)));
%find corner locations
x=[x-0.5,x+0.5];
y=[y-0.5,y+0.5];
d = sqrt(x.^2+y.^2); %distance to closed and furthest corner
if max(d)<r,a=1;return;end %inside circle
if min(d)>r,a=0;return;end %outside circle
%intersections with edges (r^2 = x^2+y^2)
inters = [sqrt(r^2-y(1)^2),sqrt(r^2-y(2)^2),sqrt(r^2-x(1)^2),sqrt(r^2-x(2)^2)]; %x(1) x(2) y(1) y(2)
%remove imaginary and out of range intersections
inters(imag(inters)~=0)=NaN;
inters(inters<1E-5)=NaN; %to find values that are zero
inters([~((x(1)<inters(1:2))&(inters(1:2)<x(2))),~((y(1)<inters(3:4))&(inters(3:4)<y(2)))])=NaN;
idx = find(~isnan(inters));
if numel(idx)~=2,error('need two intersections of circle with pixel');end
%check area of pixel inside circumference
if all(idx==[1,2]) %2 intersections on y-edge
a=(F(y(2),r)-F(y(1),r)) - x(1); %area
elseif all(idx==[3,4]) %2 intersections on x-edge
a=(F(x(2),r)-F(x(1),r)) - y(1); %area
elseif all(idx==[1,3]) %one intersection on y-edge one on x-edge (left&bottom)
a=(F(inters(1),r)-F(x(1),r))- (y(1)*(inters(1)-x(1)));
elseif all(idx==[2,4]) %one intersection on y-edge one on x-edge (top&right)
a=(inters(2)-x(1))+(F(x(2),r)-F(inters(2),r))-(y(1)*(x(2)-inters(2)));
else
error('geometry')
end
a=real(a);
if a<0||a>1
error('computational error');
end
end
Script to test the function
M = ones(100); %data
M(1:50,:)=0;
pos=[50.2,50];
r = 2;
%calculate what the result should be
h=50-pos(2)+0.5;
A=pi*r^2;
wedge = acos(h/r)/pi;
triangle = h*sqrt(r^2-h^2);
res=(A*wedge-triangle)/A
S=0;N=0;
for i = 1:size(M,1)
for j = 1:size(M,2)
x=abs(j-pos(1));
y=abs(i-pos(2));
n=incirc( x,y,r );
M_(i,j)=n;
S = S+M(i,j)*n;
N = N+n;
end
end
result = S/N
result = 0.3425
You can see the algorithm finds the part of the pixel in the circle.
The question is missing a question, but I'll assume that it's not how to calculate whether pixels are fully inside or outside the circle. That's a relatively simple task. That is, a pixel is fully inside if the furtherest corner of the pixel to the centre is less than a radius away from the centre, and a pixel is fully outside if the closest corner of the pixel to the centre is more than a radius away from the centre.
The question of what proportion of pixels on the circumference fall within the circumference is much trickier. There are two fundamental solutions:
Exact and hard.
Approximate and a bit easier.
In both cases, note the horizontal and vertical symmetry means only the top right quadrant need be considered.
Then, for (1), translate the circle centre to the origin (0, 0) and treat the circumference as the function y(x) = sqrt(r^2 - x^2). Then, the area of an overlapping pixel within the circle is the integral:
integral(y(x) - y0, from x0 to x1, with respect to x)
where y0 is the bottom coordinate of the pixel, x0 is the left coordinate and x1 is the right coordinate.
This integral can be solved exactly with a trigonometric identity and a trigonometric substitution.
For (2), just generate a set of random points within the pixel and count how many of them fall within the circumference. As the set gets larger, the proportion of points that fall within the circumference to the count of all point approaches the proportion of the pixel within the circumference.
You can use inpolygon, to get the indices which lie inside the circle, once you have those indices you can get your pixels and do what you want.
M = rand(100); %data
[nx,ny] = size(M) ;
[X,Y] = meshgrid(1:ny,1:nx) ;
pos=[20,20];
r = 5;
phi=linspace(0,2*pi,100);
imagesc(M);
axis image
hold on
plot(pos(1),pos(2),'rx')
xc = pos(1)+r*sin(phi) ;
yc = pos(2)+r*cos(phi) ;
plot(xc,yc,'-r');
% hold off
%% get indices which are inside the circle
idx = inpolygon(X(:),Y(:),xc,yc) ;
xi = X(idx) ; yi = Y(idx) ;
plot(xi,yi,'.r')
mypixels = M(idx) ;
You can also use rangesearch to get the points lying within the given radius of the circle. As below:
M = rand(100); %data
[nx,ny] = size(M) ;
[X,Y] = meshgrid(1:ny,1:nx) ;
pos=[20,20];
r = 5;
phi=linspace(0,2*pi,100);
imagesc(M);
axis image
hold on
plot(pos(1),pos(2),'rx')
xc = pos(1)+r*sin(phi) ;
yc = pos(2)+r*cos(phi) ;
plot(xc,yc,'-r');
% hold off
%% Use nearest neighbour search
idx = rangesearch([X(:),Y(:)],pos,r) ;
xi = X(idx{1}) ; yi = Y(idx{1}) ;
plot(xi,yi,'.r')
mypixels = M(idx{1}) ;
I am trying to detect a bent conveyor in an image. I used the following code using Hough transform to detect its edges
%# load image, and process it
I = imread('ggp\2.jpg');
g = rgb2gray(I);
bw = edge(g,'Canny');
[H,T,R] = hough(bw);
P = houghpeaks(H,500,'threshold',ceil(0.4*max(H(:))));
% I apply houghlines on the grayscale picture, otherwise it doesn't detect
% the straight lines shown in the picture
lines = houghlines(g,T,R,P,'FillGap',5,'MinLength',50);
figure, imshow(g), hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
deltaY = xy(2,2) - xy(1,2);
deltaX = xy(2,1) - xy(1,1);
angle = atan2(deltaY, deltaX) * 180 / pi;
if (angle == 0)
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
% Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
end
end
As it is shown, two straight lines successfully detect top and bottom edges of the conveyor but I don't know how to detect if it is bent or not (in the picture it is bent) and how to calculate the degree of that.
The curve approximately is drawn manually in the picture below (red color):
I found no code or function for Hough transform in matlab to detect such smooth curves (e.g., 2nd degree polynomials: y= a*x^2). Any other solution is also welcome.
It's the original image:
Looking at your straight lines detecting the conveyor belt, I assume you can focus your processing around the region of interest (rows 750 to 950 in the image).
Proceeding from that point:
oimg = imread('http://i.stack.imgur.com/xfXUS.jpg'); %// read the image
gimg = im2double( rgb2gray( oimg( 751:950, :, : ) ) ); %// convert to gray, only the relevant part
fimg = imfilter(gimg, [ones(7,50);zeros(1,50);-ones(7,50)] ); %// find horizontal edge
Select only strong horizontal edge pixels around the center of the region
[row, col] = find(abs(fimg)>50);
sel = row>50 & row < 150 & col > 750 & col < 3250;
row=row(sel);
col=col(sel);
Fit a 2nd degree polynom and a line to these edge points
[P, S, mu] = polyfit(col,row,2);
[L, lS, lmu] = polyfit(col, row, 1);
Plot the estimated curves
xx=1:4000;
figure;imshow(oimg,'border','tight');
hold on;
plot(xx,polyval(P,xx,[],mu)+750,'LineWidth',1.5,'Color','r');
plot(xx,polyval(L,xx,[],lmu)+750,':g', 'LineWidth', 1.5);
The result is
You can visually appreciate how the 2nd degree fit P fits better the boundary of the conveyor belt. Looking at the first coefficient
>> P(1)
ans =
1.4574
You see that the coefficient of x^2 of the curve is not negligible making the curve distinctly not a straight line.
I have an assignment to render a torus. This is my first time with matlab and i've managed to struggle along and get 2/3 parts done with some horrible kludged code.
The first step of the assignment is to render a circle as a set of 20 points. For which i produced:
circle (IMG)
Then the next step is to rotate and translate that circle and draw it 20 times to represent a torus shape, so i got this:
torus points (IMG)
The next step is to render a 3d representation of this torus from the list of vertices.
What I have is massive a list of a vertices in a 400x3 matrix like so:
7.66478245119846 -1.84059939326890 0.292371704722737
7.53434247103331 -1.79821687453702 0.573576436351046
7.32764268084884 -1.73105604149887 0.798635510047293
7.06491629627043 -1.64569106442929 0.945518575599317
6.77188080634298 -1.55047806205660 0.999847695156391
6.47722056651889 -1.45473714644104 0.956304755963036
... ... ...
where each subsequent 20 rows is another circle.
The assignment recommends that I use the surf function in order to render this but I can't figure out how. All the examples I've seen use surf to represent 2 dimensional planes that get distorted by a height value. Which doesn't seem appropriate for rendering this kind of 3 dimensional shape at all.
The approach I'm trying is to build a list of faces and then using the patch function to render the circle. Where the first 2 points of each circle makes a square with the corresponding 2 points of the next circle, then rendering.
Using something like this:
for i=1:400
face = [(i) (i+1) (i+21) (i+20)];
patch('Faces',face,'Vertices',torus_vertices,'FaceColor','r'); %Should do this at the end
end
For which i get something like this:
3d Torus (IMG)
It twists and and some of the side and inner side faces are messed up. I think it might have something to do with the ordering of the vertices flipping around at some point.
What would be the best way to approach this problem? If at all possible i want to do it with the surf function.
Ex1.m
%Initial positions
position = [2 0 0];
normal = [0 1 0];
%Rotation matrix
rotate18 = [cos(todeg(18)) -sin(todeg(18)) 0;
sin(todeg(18)) cos(todeg(18)) 0;
0 0 1];
% translate along the x axis by 5
translate = [5 0 0];
%% iterate 20 times to get a list of all the vertices
taurus_vertices = zeros(0, 3);
for i=0:20
%rotate translation by 18 degrees
translate = translate * rotate18;
%translate
position = position + translate;
%rotate the normal so it faces the right direction
normal = normal * rotate18;
%Get vertices for the circle and append to vertices list
circle_vertices = circle_3D(1, position, normal);
taurus_vertices = cat(1, taurus_vertices, circle_vertices);
%translate back to original position
position = position - translate;
end
%scatter3(taurus_vertices(1:end, 1), taurus_vertices(1:end, 2), taurus_vertices(1:end, 3));
%% Render each face
for i=1:400
face = [(i) (i+1) (i+21) (i+20)];
patch('Faces',face,'Vertices',taurus_vertices,'FaceColor','r');
end
circle.m
function h_circle=circle_3D(r, M, n)
%% Prepare input parameters
if size(n,2)>size(n,1)
n=n';
end
if size(M,2)>size(M,1)
M=M';
end
%% Define unit vectors u and v
% u and v define a new coordinate system in a plane perpendicular to n
a=[1;0;0];
b=[0;1;0];
if isempty(find(cross(a,n), 1))==1
a=[0;0;1];
elseif isempty(find(cross(b,n), 1))==1
b=[0;0;1];
end
alpha=dot(n,a)/dot(n,n);
u=a-alpha*n;
v=cross(u,n);%b-beta*n-gamma*u;
u=u/sqrt(sum(u.*u));
v=v/sqrt(sum(v.*v));
%% Plot the circle
hold on
axis equal
degs = 0;
points = 0;
verts = zeros(20, 3);
for phi=0: pi()/180 : 2*pi()
degs=degs+1;
if (mod(degs,18) == 0 )
points = points + 1;
verts(points,1)=M(1,1)+r*cos(phi)*u(1,1)+r*sin(phi)*v(1,1);
verts(points,2)=M(2,1)+r*cos(phi)*u(2,1)+r*sin(phi)*v(2,1);
verts(points,3)=M(3,1)+r*cos(phi)*u(3,1)+r*sin(phi)*v(3,1);
end
end
h_circle= verts;
Your problem is perfect for trisurf- given a set of points, you need to build a triplet to connect a mesh to.
For your problem, you can use:
%inner circle points and radius
N1=20;
r1=1;
%outer circle points and radius
N2=30;
r2=5;
%inner cicle angles
thC=linspace(0,2*pi*(1-1/N1),N1)';
%inner cicle points
xyzC=[r1*sin(thC), zeros(N1,1),r1*cos(thC)]';
%torus points
xyzT = zeros(3,N1*N2);
for i=1:N2
%circle transformation
thT = 2*pi*i/N2;
T = [1 0 0 r2*cos(thT); 0 1 0 r2*sin(thT);0 0 1 0]*[cos(thT) -sin(thT) 0 0;sin(thT) cos(thT) 0 0 ; 0 0 1 0; 0 0 0 1];
%add points
xyzT(:,(i-1)*N1+1:i*N1)=T*[xyzC ;ones(1,N1)];
end
%build patch triples
tri=[];
for i=1:N2
for j=1:N1
%get three points:
% jth from ith circle
% j+1th from ith circle
% jth from i+1th circle
tri(end+1,:)=[(i-1)*N1+j (i-1)*N1+j+1 i*N1+j];
%get three points:
% j+1th from ith circle
% j+1th from i+1th circle
% jth from i+1th circle
tri(end+1,:)=[ i*N1+j (i-1)*N1+j+1 i*N1+j+1];
end
end
tri=mod(tri-1,N1*N2)+1;
trisurf(tri,xyzT(1,:),xyzT(2,:),xyzT(3,:));axis equal
%fancy
shading interp
camlight left
and get:
Thank you for the example. It would of been nicer to render the torus using triangle instead of rectangles but deadline is like an hour away and I managed to get my current one working!
I figured out what was causing my issues. Rotating the translation matrix was having an adverse effect on the orientation of each circles points (they don't line up), causing it to twist.
After looking through the notes more thoroughly (that is going several years worth of online notes back), I managed to find some psuedo code for a sweep function that I used to completely rewrite. I now generate 20 circles in the same spot, and rotate each one around the origin by increasing amounts instead. Which led to this:
%% Settings
points = 20; %Number of points in each circle
circles = 20; %Number of circles making up the torus
radius = 1; %Radius of the circle
scale = 0.75; %Scale to apply to the whole torus
center = [2 0 0]; %Center point of the first circle to sweep into a torus
%% Create (circles+1) circles after the other in an array at point [2 0 0]
%The extra circle overlaps the first, this is to make face generation much
%simpler.
V = zeros(circles*points, 3);
for i=0:points:points*circles
for k=1:points
V(i+k,1) = center(1) + radius * cosd((k-1)*(360/points));
V(i+k,2) = center(2) + 0;
V(i+k,3) = center(3) + radius * sind((k-1)*(360/points));
end
end
%% Sweep the circles, rotate each circle 18 degrees more than the previous
for n=0:points:circles*points
%Calculate degrees for current circle
D = (n/points) * 360/circles;
%Create a Z-rotation matrix
Rz = [
cosd(D) sind(D) 0;
-sind(D) cosd(D) 0;
0 0 1;
];
%Rotate each point of the circle
for i=1:points
V(n+i, :) = Rz * V(n+i, :)';
end
end
%% Scale the torus
%Create a scalar matrix
S = [
scale 0 0;
0 scale 0;
0 0 scale
];
%Scale each point
for n=0:points:circles*points
for i=1:points
V(n+i, :) = S * V(n+i, :)';
end
end
%% Generate faces
F = zeros(circles*points, 4);
for n=1:points:circles*points
for k=1:points
%If it's an endface then have destination face vertices wrap around to the first face of the current circle
if(mod(k, points) == 0)
F((n-1)+k,2)= (n-1)+k+1 - points;
F((n-1)+k,3)= n+points+k - points;
else
%otherwise use the next faces starting vertices
F((n-1)+k,2)= (n-1)+k+1;
F((n-1)+k,3)= n+points+k;
end
%Set the points coming from the previous face
F((n-1)+k,1)= (n-1)+k;
F((n-1)+k,4)= n+points+k-1;
end
end
%% Render
%Configure renderer
axis equal;
hold on;
%Render points
scatter3(V(1:end, 1), V(1:end, 2), V(1:end, 3), 'MarkerEdgeColor', 'b');
%Render faces
patch('Faces', F, 'Vertices', V, 'FaceColor', 'g');
Which makes:
If I have points in a graph in matlab that are randomly sorted and when plotted produce various closed shapes. Given a specific point on the left side of one of the closed shapes how can I get all the points of that shape in a vector form keeping in mind the convention of collecting the points is moving in a clockwise direction.
A commented example:
cla
% Random data
x = rand(15,1);
y = rand(15,1);
scatter(x,y)
% Random point to the left
hold on
p = [-0.1, rand(1)*0.2 + 0.5];
plot(p(1),p(2),'*r')
% Separate points that lie above your point
idx = y >= p(2);
% Sort x then y increasing for upper half and x then y decreasing for lower half
shape = [sortrows([x( idx) y( idx)],[1 2])
sortrows([x(~idx) y(~idx)],[-1 -2])];
Check that shape contains clockwise sorted coordinates by plotting an open line:
% Plot clockwise open line
plot(shape(1:end ,1),shape(1:end,2),'k')