Estimate the amount of the area of the hemisphere’s surface which can be seen by the eye? - matlab

We suppose that there are one hemisphere and three triangles in a 3D space. The center point of the hemisphere’s bottom is denoted by C. The radius of the hemisphere’s bottom is represented by R. The normal vector to hemisphere’s bottom is denoted by n.
The first triangle is given by the three points V1, V2 and V3. The second triangle is given by the three points V4, V5 and V6. The third triangle is given by the three points V7, V8 and V9. The positions of the points V1, V2, …, V9 are arbitrary. Now, we further assume that an eye is located at the point E. Note that the triangles may block the line of sight from the eye to the hemisphere’s surface; hence some region of the hemisphere’s surface may not be seen by the eye.
Please develop a method to estimate the amount of the area of the hemisphere’s surface which can be seen by the eye?
Here is a code for the rectangle rather than hemisphere:
function r = month_1()
P1 = [0.918559, 0.750000, -0.918559];
P2 = [0.653394, 0.649519, 1.183724];
P3 = [-0.918559, -0.750000, 0.918559];
P4 = [-0.653394, -0.649519, -1.183724];
V1 = [0.989609, -1.125000, 0.071051];
V2 = [1.377838, -0.808013, -0.317178];
V3 = [1.265766, -0.850481, 0.571351];
V4 = [0.989609, -1.125000, 0.071051];
V5 = [1.265766, -0.850481, 0.571351];
V6 = [0.601381, -1.441987, 0.459279];
V7 = [0.989609, -1.125000, 0.071051];
V8 = [1.377838, -0.808013, -0.317178];
V9 = [0.713453, -1.399519, -0.429250];
E = [1.714054, -1.948557, 0.123064];
C = [0,1,0];
Radius = 2;
n = [0,1,0];
%hold on
patches.vertices(1,:)= P1;
patches.vertices(2,:)= P2;
patches.vertices(3,:)= P3;
patches.vertices(4,:)= P4;
patches.vertices(5,:)= V1;
patches.vertices(6,:)= V2;
patches.vertices(7,:)= V3;
patches.vertices(8,:)= V4;
patches.vertices(9,:)= V5;
patches.vertices(10,:)= V6;
patches.vertices(11,:)= V7;
patches.vertices(12,:)= V8;
patches.vertices(13,:)= V9;
patches.faces(1,:)= [5,6,7];
patches.faces(2,:)= [8,9,10];
patches.faces(3,:)= [11,12,13];
patches.faces(4,:)= [1,2,3];
patches.faces(5,:)= [1,3,4];
patches.facevertexcdata = 1;
patch(patches);
shading faceted; view (3);
% dispatch([1,1,1])
hold on
Num = 20;
Sum = 0;
%Srec = norm(cross(P1 - P4, P3 - P4));
for i = 1:Num
x1 = rand;
x2 = rand;
v1 = P1-P4;
v2 = P3-P4;
Samp = P4+v1*x1+v2*x2;
ABC = fun_f(E, Samp, V1,V2,V3)*fun_f(E,Samp, V4, V5, V6)*fun_f(E,Samp, V7,V8,V9);
Sum = Sum + ABC;
% if ABC ==1
% plot3(Samp(1), Samp(2), Samp(3),'r +'), hold on
% else
% plot3(Samp(1), Samp(2), Samp(3),'b +'), hold on
% end
%............................
[x, y, z]= sphere;
patches = surf2patch(x,y,z,z);
patches.vertices(:,3) = abs(patches.vertices(:,3));
patches.facevertexcdata = 1;
patch(patches)
shading faceted; view(3)
daspect([1 1 1])
%............................
end
%r = Sum/Num;
%view(31, 15)
%end
r = Sum/Num*norm(cross (P1-P4,P3-P4));
disp(sprintf('the integration is: %.5f',r));
disp(sprintf('the accurate result is: %.5f',norm(cross(P1-P4,P3-P4)/4)));
function res = fun_f(LineB, LineE, V1, V2, V3)
O = LineB;
Len = norm(LineE-LineB);
v = (LineE-LineB)/Len;
N = cross(V2-V1, V3-V1)/norm(cross(V2-V1, V3-V1));
if dot(N,v)~=0
tp = dot(N, V1-O)/ dot(N,v);
% if tp >=0 && tp <= (1:3);
P = LineB+tp*v(1:3);
A = V1 - P;
B = V2 - P;
Stri1 = norm(cross(A,B))/2;
A = V1 - P;
B = V3 - P;
Stri2 = norm(cross(A,B))/2;
A = V3 - P;
B = V2 - P;
Stri3 = norm(cross(A,B))/2;
A = V1 - V2;
B = V3 - V2;
Stotal = norm(cross(A,B))/2;
if (Stri1 + Stri2 + Stri3)> (Stotal + 1e-8)
res = 1;
else
res = 0;
end
else
res =1;
end
end
end

Take a small element of surface area centered on , dimensions . The area element is given by
The idea is to loop over these elements on the sphere; calculate the center point of the element at , and work out if the line segment between this point and the camera intersects a triangle. More here: https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm.
Now we need to find the points; trivially this means incrementing by over all of the hemisphere. But this would make the sampling resolution uneven - the factor would make the elements far larger near the apex of the hemisphere than at its edge.
Instead:
Set a fixed number N of rings to loop around, i.e. number of iterations of .
Set the minimum iteration area . The number of iterations of , M is gven by
Where is the total area of the ring at :
And of course from above the increments are given by
Loop over all the rings, being careful that gives the middle line of each ring (So start at ); same concern need not apply to due to the symmetry. For each ring loop over each , and do the line intersection test as mentioned above.
The above method reduces the amount of bias in the area sampling resolution at small .
An even better way would be Fibonacci lattices, but they are more complicated. See this paper: http://geonaut.eu/published/016_Fibonacci_Lattice.pdf

clc
%% Declaration of Initial Variables
C = [0.918559, 0.750000, -0.918559];
R = 10;
n = [1, 2, 1.5];
V1 = [0.989609, -1.125000, 0.071051];
V2 = [1.377838, -0.808013, -0.317178];
V3 = [1.265766, -0.850481, 0.571351];
V4 = [0.989609, -1.125000, 0.071051];
V5 = [1.265766, -0.850481, 0.571351];
V6 = [0.601381, -1.441987, 0.459279];
V7 = [0.989609, -1.125000, 0.071051];
V8 = [1.377838, -0.808013, -0.317178];
V9 = [0.713453, -1.399519, -0.429250];
E = [1.714054, -1.948557, 0.123064];
Num = 10000;
count1 = 0; count2 = 0; count3 = 0;
%% Calculating the triangles Normal and Area
N1 = cross((V2-V1),(V3-V1));
N2 = cross((V5-V4),(V6-V4));
N3 = cross((V8-V7),(V9-V7));
Area1 = norm(N1)/2;
Area2 = norm(N2)/2;
Area3 = norm(N3)/2;
%% Plotting the triangle
patch([V1(1),V2(1),V3(1),V1(1)],[V1(2),V2(2),V3(2),V1(2)],[V1(3),V2(3),V3(3),V1(3)], 'green');
hold on
patch([V4(1),V5(1),V6(1),V4(1)],[V4(2),V5(2),V6(2),V4(2)],[V4(3),V5(3),V6(3),V4(3)],'green');
hold on
patch([V7(1),V8(1),V9(1),V7(1)],[V7(2),V8(2),V9(2),V7(2)],[V7(3),V8(3),V9(3),V7(3)], 'green');
plot3(E(1),E(2),E(3),'ro')
hold on
%% The Loop Section
for i=1:Num
x1 = rand;
x2 = rand;
Px = R*sqrt(x1*(2-x1))*cos(2*pi*x2)+C(1);
Py = R*sqrt(x1*(2-x1))*sin(2*pi*x2)+C(2);
Pz = R*(1 - x1)+C(3);
z = [0,0,1];
if norm(cross(n,z)) ~= 0
v = cross(n,z)/norm(cross(n,z));
u = cross(v,n)/norm(cross(v,n));
w = n/norm(n);
else
u = (dot(n,z)/abs(dot(n,z))).*[1,0,0];
v = (dot(n,z)/abs(dot(n,z))).*[0,1,0];
w = (dot(n,z)/abs(dot(n,z))).*[0,0,1];
end
M = [u(1),u(2),u(3),0;v(1),v(2),v(3),0;w(1),w(2),w(3),0;0,0,0,1]*...
[1,0,0,-C(1);0,1,0,-C(2);0,0,1,-C(3);0,0,0,1];
L = [Px,Py,Pz,1]*M;
Points = [L(1),L(2),L(3)];
Len = norm(E - Points);
plot3(L(1),L(2),L(3),'b.'),hold on
dv = (E - Points)/norm(E - Points);
%% Triangle 1
tp1 = dot(N1,(V1-Points))/dot(N1,dv);
if tp1>=0 && tp1<=Len
R1 = Points + tp1*dv;
A1 = norm(cross((V1-R1),(V2-R1)))/2;
A2 = norm(cross((V1-R1),(V3-R1)))/2;
A3 = norm(cross((V2-R1),(V3-R1)))/2;
if (A1+A2+A3) <= Area1
count1 = count1 + 1;
plot3(L(1),L(2),L(3),'r*')
end
end
%% Triangle 2
tp2 = dot(N2,(V4-Points))/dot(N2,dv);
if tp2>=0 && tp2<=Len
R2 = Points + tp2*dv;
A4 = norm(cross((V4-R2),(V5-R2)))/2;
A5 = norm(cross((V4-R2),(V6-R2)))/2;
A6 = norm(cross((V5-R2),(V6-R2)))/2;
if (A4+A5+A6) <= Area2
count2 = count2 + 1;
plot3(L(1),L(2),L(3),'r*')
end
end
%% Triangle 3
tp3 = dot(N3,(V7-Points))/dot(N3,dv);
if tp3>=0 && tp3<=Len
R3 = Points + tp3*dv;
A7 = norm(cross((V7-R3),(V8-R3)))/2;
A8 = norm(cross((V7-R3),(V9-R3)))/2;
A9 = norm(cross((V8-R3),(V9-R3)))/2;
if (A7+A8+A9) <= Area3
count3 = count3 + 1;
plot3(L(1),L(2),L(3),'r*')
end
end
end
%% Final Solution
AreaofHemi = 2*pi*R^2;
Totalcount = count1 + count2 + count3;
Areaseen=((Num-Totalcount)/Num)*AreaofHemi;
disp(fprintf('AreaofHemi %f, AreaSeen %f ',AreaofHemi,Areaseen))

Related

Active contours with open ends

Does anyone know how to make an open active contour? I'm familiar with closed contours and I have several Matlab programs describing them. I've tried to change the matrix P but that was not enough: My Matlab code is as follows:
% Read in the test image
GrayLevelClump=imread('cortex.png');
cortex_grad=imread('cortex_grad.png');
rect=[120 32 340 340];
img=imcrop(GrayLevelClump,rect);
grad_mag=imcrop(cortex_grad(:,:,3),rect);
% Draw the initial snake as a line
a=300;b=21;c=21;d=307;
snake = brlinexya(a,b,c,d); % startpoints,endpoints
x0=snake(:,1);
y0=snake(:,2);
N=length(x0);
x0=x0(1:N-1)';
y0=y0(1:N-1)';
% parameters for the active contour
alpha = 5;
beta = 10;
gamma = 1;
kappa=1;
iterations = 50;
% Make a force field
[u,v] = GVF(-grad_mag, 0.2, 80);
%disp(' Normalizing the GVF external force ...');
mag = sqrt(u.*u+v.*v);
px = u./(mag+(1e-10)); py = v./(mag+(1e-10));
% Make the coefficient matrix P
x=x0;
y=y0;
N = length(x0);
a = gamma*(2*alpha+6*beta)+1;
b = gamma*(-alpha-4*beta);
c = gamma*beta;
P = diag(repmat(a,1,N));
P = P + diag(repmat(b,1,N-1), 1) + diag( b, -N+1);
P = P + diag(repmat(b,1,N-1),-1) + diag( b, N-1);
P = P + diag(repmat(c,1,N-2), 2) + diag([c,c],-N+2);
P = P + diag(repmat(c,1,N-2),-2) + diag([c,c], N-2);
P = inv(P);
d = gamma * (-alpha);
e = gamma * (2*alpha);
% Do the modifications to the matrix in order to handle OAC
P(1:2,:) = 0;
P(1,1) = -gamma;
P(2,1) = d;
P(2,2) = e;
P(2,3) = d;
P(N-1:N,:) = 0;
P(N-1,N-2) = d;
P(N-1,N-1) = e;
P(N-1,N) = d;
P(N,N) = -gamma;
x=x';
y=y';
figure,imshow(grad_mag,[]);
hold on, plot([x;x(1)],[y;y(1)],'r');
plot(x([1 end]),y(([1 end])), 'b.','MarkerSize', 20);
for ii = 1:50
% Calculate external force
vfx = interp2(px,x,y,'*linear');
vfy = interp2(py,x,y,'*linear');
tf=isnan(vfx);
ind=find(tf==1);
if ~isempty(ind)
vfx(ind)=0;
end
tf=isnan(vfy);
ind=find(tf==1);
if ~isempty(ind)
vfy(ind)=0;
end
% Move control points
x = P*(x+gamma*vfx);
y = P*(y+gamma*vfy);
%x = P * (gamma* x + gamma*vfx);
%y = P * (gamma* y + gamma*vfy);
if mod(ii,5)==0
plot([x;x(1)],[y;y(1)],'b')
end
end
plot([x;x(1)],[y;y(1)],'r')
I've modified the coefficient matrix P in order to handle cases with open ended active contours, but that is clearly not enough.
My image:

matlab mesh2d issue which cant be found

im trying to use mesh2d function according to a guide I read.
for some reason im getting all the time this issue:
Undefined function 'mesh2d' for input arguments of type 'double'.
Error in Try1 (line 88)
[p,t] = mesh2d(allnodes, alledges);
I install mesh2d , according to the guide here:
https://github.com/dengwirda/mesh2d
but for some reason im still getting this issue...
this is my code:(im adding the code so it whould be easier in case im missing something, instead il mark the bad part)
clf
file = 'pattern3';
P = imread('Pattern3.png');
P = P(400:3400, 400:3400);
P = 255 - P*6;
P = 1-im2bw(P);
Nmin = min(size(P));
P = P(1:Nmin, 1:Nmin);
[xg, yg] = meshgrid(1:Nmin, 1:Nmin);
P((xg - Nmin/2).^2 + (yg - Nmin/2).^2 > 0.99*0.25*Nmin^2) = 0;
P = padarray(P, [1 1], 0);
CC = bwconncomp(P);
dtheta = pi/24;
theta = (-pi:dtheta:(pi-dtheta))';
nodeouter = [1.1*cos(theta) 1.1*sin(theta)];
Nnodes = length(nodeouter);
nodelist = (1:Nnodes)';
allnodes = nodeouter;
alledges = [nodelist , mod(nodelist, Nnodes)+1];
for n = 1:CC.NumObjects
%for n = 2:2
newP = zeros(size(P));
newP(CC.PixelIdxList{1,n}(:)) = 1;
newP = filter2(fspecial('average',5),newP);
C = contourc(newP,[0.2 0.2]);
C = C(:,2:end)';
C2 = dpsimplify(C,1);
m = 1;
while m <= length(C2(:,1))
if(C2(m,1) == 1 || C2(m,2) == 1)
C2(m,:) = [];
else
m = m + 1;
end
end
C2 = (C2 - Nmin/2)/(Nmin/2);
C = (C - Nmin/2)/(Nmin/2);
figure(1)
hold all
plot(C2(:,1), C2(:,2))
axis image xy
drawnow
nodeinner = C2;
Nnodeshole = length(nodeinner);
nodelist = (1:Nnodeshole)';
edgelist = [nodelist , mod(nodelist, Nnodeshole)+1];
edgelist = edgelist + Nnodes;
allnodes = [allnodes; nodeinner];
alledges = [alledges; edgelist];
Nnodes = Nnodes + Nnodeshole;
n
end
%%
hdata.fun = #(x,y) 0.05*(1 + ((x.^2 + y.^2)/a^2)).^2;
[p,t] = mesh2d(allnodes, alledges); %%here is the issue!!!!!!!!!!!!!!!!!!!!!!!1
%%
as = 0.5;
for n = 1:length(as)
a = as(n);
h = 0;
x = p(:,1);
y = p(:,2);
z = zeros(size(x));
r = sqrt(x.^2 + y.^2);
phi = atan2(y,x);
theta = atan(r/(a+h));
alpha = 2*theta;
xnew = a*sin(alpha).*cos(phi);
ynew = a*sin(alpha).*sin(phi);
znew = -a*cos(alpha);
p2 = [xnew, ynew, znew];
stlwrite('Test.stl', t, p2)
fv.faces = t;
fv.vertices = p2;
clf
figure(3)
patch(fv, 'FaceColor', [1 1 1], 'EdgeColor', 'black', 'LineWidth', 0.1)
axis equal
axis off
xlim([-a a])
ylim([-a a])
zlim([-a a])
camlight head
view(58,28)
zoom(1.5)
drawnow
end
the photo im trying to use:
I recently completely rewrote MESH2D -- bringing it up-to-date with more recent meshing techniques and MATLAB functionality. It looks like you are trying to use subroutines from old versions of the library.
Based on the updates, the routines you want are refine2 and smooth2 (they build and then optimise a two-dimensional constrained Delaunay triangulation).
I recommend that you have a look at the example code contained in tridemo to see how the updated MESH2D toolbox works.

Why do the plot and patch commands both not execute in Matlab?

So I was tasked with plotting the Golden Rectangles along with the Golden Spiral over top of the rectangles. We were given the code for the rectangles, for the "spiral" I used multiple arcs from this forum post, and I can only use if and for statements. The code for the rectangles works and the code for the spiral almost works, but what I really need is to get the patch to display behind the plot. This is the code that I have now:
clear variables; close all; clc
phi = (1+sqrt(5))/2;
x0 = 0;
y0 = 0;
for i = 1:8
edgeLength = 1/(phi^(i-1));
moveLength = 1/(phi^i);
modStep = mod(i,4);
if (modStep == 1) %move W, orient NW
x0 = x0 - moveLength;
sx = [x0 x0 x0-edgeLength x0-edgeLength];
sy = [y0 y0+edgeLength y0+edgeLength y0];
%spiral
P1 = [(x0-edgeLength);y0];
P2 = [x0;(y0+edgeLength)];
P0 = [x0;y0];
n = 1000;
v1 = P1-P0;
v2 = P2-P0;
c = det([v1,v2]);
a = linspace(0,atan2(abs(c),dot(v1,v2)),n);
v3 = [0,-c;c,0]*v1;
v = v1*cos(a)+((norm(v1)/norm(v3))*v3)*sin(a);
if i == 1
vx1 = v(1,:);
vy1 = v(2,:);
elseif i == 5
vx6 = (v(1,:)+(1/(phi^5)));
vy6 = (v(2,:)+(1/(phi^5)));
end
end
if (modStep == 2) %move N, orient NE
y0 = y0 + moveLength;
sx = [x0 x0+edgeLength x0+edgeLength x0];
sy = [y0 y0 y0+edgeLength y0+edgeLength];
%spiral
P1 = [x0;(y0+edgeLength)];
P2 = [(x0+edgeLength);y0];
P0 = [x0;y0];
n = 1000;
v1 = P1-P0;
v2 = P2-P0;
c = det([v1,v2]);
a = linspace(0,atan2(abs(c),dot(v1,v2)),n);
v3 = [0,-c;c,0]*v1;
v = v1*cos(a)+((norm(v1)/norm(v3))*v3)*sin(a);
if i == 2
vx2 = v(1,:);
vy2 = (v(2,:)+(1/(phi^2)));
elseif i == 6
vx5 = (v(1,:)+(1/(phi^5)));
vy5 = (v(2,:)+(1/(phi^6)));
end
end
if (modStep == 3) %move E, orient SE
x0 = x0 + moveLength;
sx = [x0 x0 x0+edgeLength x0+edgeLength];
sy = [y0 y0-edgeLength y0-edgeLength y0];
%spiral
P1 = [(x0+edgeLength);y0];
P2 = [x0;(y0-edgeLength)];
P0 = [x0;y0];
n = 1000;
v1 = P1-P0;
v2 = P2-P0;
c = det([v1,v2]);
a = linspace(0,atan2(abs(c),dot(v1,v2)),n);
v3 = [0,-c;c,0]*v1;
v = v1*cos(a)+((norm(v1)/norm(v3))*v3)*sin(a);
if i == 3
vx3 = (v(1,:)+(1/(phi^3)));
vy3 = (v(2,:)+(1/(phi^2)));
elseif i == 7
vx7 = (v(1,:)+(1/(phi^7)));
vy7 = (v(2,:)+(1/(phi^6)));
end
end
if (modStep == 0) %move S, orient SW
y0 = y0 - moveLength;
sx = [x0 x0-edgeLength x0-edgeLength x0];
sy = [y0 y0 y0-edgeLength y0-edgeLength];
%spiral
P1 = [(x0-edgeLength);y0];
P2 = [x0;(y0-edgeLength)];
P0 = [x0;y0];
n = 1000;
v1 = P1-P0;
v2 = P2-P0;
c = det([v1,v2]);
a = linspace(0,atan2(abs(c),dot(v1,v2)),n);
v3 = [0,-c;c,0]*v1;
v = v1*cos(a)+((norm(v1)/norm(v3))*v3)*sin(a);
if i == 4
vx4 = (v(1,:)+(1/(phi^3)));
vy4 = (v(2,:)+(1/(phi^3)));
elseif i == 8
vx8 = (v(1,:)+(1/(phi^7)));
vy8 = (v(2,:)+(1/(phi^7)));
end
end
end
patch(sx,sy,0.8+0.2*rand(1,3));
vx = [vx1 vx2 vx3 vx4 vx5 vx6 vx7 vx8];
vy = [vy1 vy2 vy3 vy4 vy5 vy6 vy7 vy8];
plot(vx,vy);
axis equal
In the code, the comments about North, West, etc. are in reference to the rectangles that are displayed and their orientation. The parts of the code that make up the spiral are likewise labeled.
So I really have two questions, however, the one that is most pressing is why will only the plot(vx,vy) command only work and not the patch? I tried looking at other examples of things but they seem to just type each command in in the order they want them to print and it does it.
The other issue I have it that when I do run this code the arcs work perfectly for i = 1:4 but after that, you can see, the lines are all messed up. I don't really know why that is either.
If I left out any other information I'm sorry!
Thank you

Best way to get the bounding rectangle of a set of 3D points on a plane in Matlab

I need to get the four edges of the bounding rectangle of a set of 3D points stored as a 3xN matrix (tt). N >=4. The points lies on a plane.
Code sample:
% Simulate some points
deltaXY = 20;
[xx,yy] = meshgrid(-100:deltaXY:100,-100:deltaXY:100);
XYZ = [xx(:)'; yy(:)'; zeros(1,numel(xx))];
% Add some imperfection to data removing the top rigth point
maxXids = find(XYZ(1,:) == max(XYZ(1,:)));
maxYids = find(XYZ(2,:) == max(XYZ(2,:)));
id = intersect(maxXids,maxYids);
XYZ = removerows(XYZ',id)';
% Lets rotate a bit
XYZ = roty(5)*rotx(7)*rotz(0)*XYZ;
% Plot points
figure;
grid on;
rotate3d on;
axis vis3d;
hold on;
plot3(XYZ(1,:),XYZ(2,:),XYZ(3,:),'.r');
% Find bounding rectangle
% ??? :(
%Currently I'm using this code:
tt = XYZ;
%Get the max and min indexes
minX = find(tt(1,:) == min(tt(1,:)));
minY = find(tt(2,:) == min(tt(2,:)));
maxX = find(tt(1,:) == max(tt(1,:)));
maxY = find(tt(2,:) == max(tt(2,:)));
%Intersect to find the common index
id1 = intersect(minX,minY);
id2 = intersect(maxX,minY);
id3 = intersect(maxX,maxY);
id4 = intersect(minX,maxY);
%Get the points
p1 = tt(:,id1(1));
p2 = tt(:,id2(1));
p3 = tt(:,id3(1));
p4 = tt(:,id4(1));
Sample points plot:
The problem is that intersect some times can be null, eg: if the points does not form a rectangle. Resulting this error:
Index exceeds matrix dimensions.
First solution : Use logical indexing to get rid of the find calls
p1=tt(:,tt(1,:)==min(tt(1,:))&tt(2,:)==min(tt(2,:)));
p2=tt(:,tt(1,:)==max(tt(1,:))&tt(2,:)==min(tt(2,:)));
p3=tt(:,tt(1,:)==max(tt(1,:))&tt(2,:)==max(tt(2,:)));
p4=tt(:,tt(1,:)==min(tt(1,:))&tt(2,:)==max(tt(2,:)));
Second solution : Use convhull to get the corners :
k=convhull(tt(1,:),tt(2,:));
Corners=[tt(:,k(1:end-1))];
Ok found a solution:
% Find bounding rectangle
tt = XYZ;
%Get the max and min indexes
minXids = find(tt(1,:) == min(tt(1,:)));
minYids = find(tt(2,:) == min(tt(2,:)));
maxXids = find(tt(1,:) == max(tt(1,:)));
maxYids = find(tt(2,:) == max(tt(2,:)));
%Intersect to find the common index
id1 = intersect(minXids,minYids);
id2 = intersect(maxXids,minYids);
id3 = intersect(maxXids,maxYids);
id4 = intersect(minXids,maxYids);
%Get the points
% Find affine plane on points
[np,~,pp] = affine_fit(tt');
% Converts to cart. eq.
% ax + yb + cz + d = 0
% Find d
a = np(1); b = np(2); c = np(3);
x = pp(1); y = pp(2); z = pp(3);
d = - (a*x + y*b + c*z);
% Get only one value
minX = min(tt(1,minXids)); maxX = max(tt(1,maxXids));
minY = min(tt(2,minYids)); maxY = max(tt(2,maxYids));
if numel(id1) == 0
x = minX; y = minY;
% Calculate z at xy.
z = - (d + a*x + y*b)/c;
p1 = [x y z]';
else
p1 = tt(:,id1(1));
end
if numel(id2) == 0
x = maxX; y = minY;
z = - (d + a*x + y*b)/c;
p2 = [x y z]';
else
p2 = tt(:,id1(1));
end
if numel(id3) == 0
x = maxX; y = maxY;
z = - (d + a*x + y*b)/c;
p3 = [x y z]';
else
p3 = tt(:,id1(1));
end
if numel(id4) == 0
x = minX; y = maxY;
z = - (d + a*x + y*b)/c;
p4 = [x y z]';
else
p4 = tt(:,id1(1));
end
ps = [p1 p2 p3 p4];
plot3(ps(1,:),ps(2,:),ps(3,:),'ob');

Frank - Wolfe Algorithm in matlab

I'm trying to solve the following question :
maximize x^2-5x+y^2-3y
x+y <= 8
x<=2
x,y>= 0
By using Frank Wolf algorithm ( according to http://web.mit.edu/15.053/www/AMP-Chapter-13.pdf ).
But after running of the following program:
syms x y t;
f = x^2-5*x+y^2-3*y;
fdx = diff(f,1,x); % f'x
fdy = diff(f,1,y); % y'x
x0 = [0 0]; %initial point
A = [1 1;1 0]; %constrains matrix
b = [8;2];
lb = zeros(1,2);
eps = 0.00001;
i = 1;
X = [inf inf];
Z = zeros(2,200); %result for end points (x1,x2)
rr = zeros(1,200);
options = optimset('Display','none');
while( all(abs(X-x0)>[eps,eps]) && i < 200)
%f'x(x0)
c1 = subs(fdx,x,x0(1));
c1 = subs(c1,y,x0(2));
%f'y(x0)
c2 = subs(fdy,x,x0(1));
c2 = subs(c2,y,x0(2));
%optimization point of linear taylor function
ys = linprog((-[c1;c2]),A,b,[],[],lb,[],[],options);
%parametric representation of line
xt = (1-t)*x0(1)+t*ys(1,1);
yt = (1-t)*x0(2)+t*ys(2,1);
%f(x=xt,y=yt)
ft = subs(f,x,xt);
ft = subs(ft,y,yt);
%f't(x=xt,y=yt)
ftd = diff(ft,t,1);
%f't(x=xt,y=yt)=0 -> for max point
[t1] = solve(ftd); % (t==theta)
X = double(x0);%%%%%%%%%%%%%%%%%
% [ xt(t=t1) yt(t=t1)]
xnext(1) = subs(xt,t,t1) ;
xnext(2) = subs(yt,t,t1) ;
x0 = double(xnext);
Z(1,i) = x0(1);
Z(2,i) = x0(2);
i = i + 1;
end
x_point = Z(1,:);
y_point = Z(2,:);
% Draw result
scatter(x_point,y_point);
hold on;
% Print results
fprintf('The answer is:\n');
fprintf('x = %.3f \n',x0(1));
fprintf('y = %.3f \n',x0(2));
res = x0(1)^2 - 5*x0(1) + x0(2)^2 - 3*x0(2);
fprintf('f(x0) = %.3f\n',res);
I get the following result:
x = 3.020
y = 0.571
f(x0) = -7.367
And this no matter how many iterations I running this program (1,50 or 200).
Even if I choose a different starting point (For example, x0=(1,6) ), I get a negative answer to most.
I know that is an approximation, but the result should be positive (for x0 final, in this case).
My question is : what's wrong with my implementation?
Thanks in advance.
i changed a few things, it still doesn't look right but hopefully this is getting you in the right direction. It looks like the intial x0 points make a difference to how the algorithm converges.
Also make sure to check what i is after running the program, to determine if it ran to completion or exceeded the maximum iterations
lb = zeros(1,2);
ub = [2,8]; %if x+y<=8 and x,y>0 than both x,y < 8
eps = 0.00001;
i_max = 100;
i = 1;
X = [inf inf];
Z = zeros(2,i_max); %result for end points (x1,x2)
rr = zeros(1,200);
options = optimset('Display','none');
while( all(abs(X-x0)>[eps,eps]) && i < i_max)
%f'x(x0)
c1 = subs(fdx,x,x0(1));
c1 = subs(c1,y,x0(2));
%f'y(x0)
c2 = subs(fdy,x,x0(1));
c2 = subs(c2,y,x0(2));
%optimization point of linear taylor function
[ys, ~ , exit_flag] = linprog((-[c1;c2]),A,b,[],[],lb,ub,x0,options);
so here is the explanation of the changes
ub, uses our upper bound. After i added a ub, the result immediately changed
x0, start this iteration from the previous point
exit_flag this allows you to check exit_flag after execution (it always seems to be 1 indicating it solved the problem correctly)