function spray_angle_demo
im=imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/122806/im1.jpg');
bw=max(im,[],3)>100;
clear im
L=bwlabel(bw);
N=max(L(:));
if N>1
RP=regionprops(L,'Area');
A=zeros(N,1);
for i=1:N, A(i)=RP(i).Area; end
[~,id]=max(A);
bw=L==id;
end
clear L
figure
imshow(bw)
axis on
hold on
XY=bwboundaries(bw,8,'noholes');
XY=XY{1}(:,[2 1]);
CH=convhull(XY,'simplify',true);
CH=flipud(CH);
B=XY(CH,:);
plot(B(:,1),B(:,2),'--r','LineWidth',2)
B(end,:)=[];
[~,id_top]=min(B(:,2));
B=circshift(B ,[1-id_top 0]);
[~,id_lft]=min(B(:,1));
B_lft=B(1:id_lft,:);
[~,id_rgt]=max(B(:,1));
B_rgt=B;
B_rgt(2:(id_rgt-1),:)=[];
B_rgt=circshift(B_rgt,[-1 0]);
B_rgt=flipud(B_rgt);
E_lft=straight_edge_segment(B_lft);
E_rgt=straight_edge_segment(B_rgt);
P=LineIntersection(E_lft(1,:),E_lft(2,:),E_rgt(1,:),E_rgt(2,:));
E_lft(1,:)=P;
E_rgt(1,:)=P;
plot(E_lft(:,1),E_lft(:,2),'-g','LineWidth',3)
plot(E_rgt(:,1),E_rgt(:,2),'-g','LineWidth',3)
plot(P(1),P(2),'*y','MarkerSize',15,'LineWidth',3)
d_lft=E_lft(2,:)-E_lft(1,:);
d_lft=d_lft/norm(d_lft);
d_rgt=E_rgt(2,:)-E_rgt(1,:);
d_rgt=d_rgt/norm(d_rgt);
t=(180/pi)*acos(dot(d_lft,d_rgt));
fprintf('Spray angle: %.2f degrees\n',t)
function E=straight_edge_segment(B)
N=size(B,1);
E=B(1:2,:);
if N==2, return; end
D=B(2:N,:)-B(1:(N-1),:);
L=sqrt(sum(D.^2,2));
L_net=sum(L);
L=L(1);
i=2;
f=L/L_net;
df=0;
t_thr=5;
while f<.99 && df<(2/3)
i=i+1;
L=L + norm(B(i,:)-E(end,:));
fi=L/L_net;
df=fi-f;
f=fi;
De=E(end,:)-E(1,:);
De=De/norm(De);
Di=B(i,:)-E(end,:);
Di=Di/norm(Di);
t=dot(De,Di);
t(t>1)=1;
t=acos(t)*(180/pi);
if t<t_thr
E=cat(1,E,B(i,:));
elseif size(E,1)>2
De=E(end,:)-E(2,:);
De=De/norm(De);
Di=B(i,:)-E(end,:);
Di=Di/norm(Di);
t=dot(De,Di);
t(t>1)=1;
t=acos(t)*(180/pi);
if t<t_thr
E=cat(1,E,B(i,:));
E(1,:)=[];
else
break
end
elseif f<0.99
E=cat(1,E,B(i,:));
E(1,:)=[];
else
break
end
end
E=cat(1,E(1,:),E(end,:));
function P=LineIntersection(A1,A2,B1,B2)
Daa=sum((A2-A1).^2,2);
Dbb=sum((B2-B1).^2,2);
Dab=sum((A2-A1).*(B2-B1),2);
N=size(A1,1);
S=zeros(2,2,N);
S(1,1,:)= Daa(:)+eps;
S(1,2,:)=-Dab(:);
S(2,1,:)=-Dab(:);
S(2,2,:)= Dbb(:)+eps;
g=[sum((A2-A1).*(A1-B1),2) -sum((B2-B1).*(A1-B1),2)];
g=permute(g,[2 3 1]);
t=Cramer_2by2_Inverse(S,-g);
t=permute(t,[3 1 2]);
P=bsxfun(@times,t(:,1),A2-A1) + A1;
function uv=Cramer_2by2_Inverse(A,b)
detA=A(1,1,:).*A(2,2,:)-A(1,2,:).*A(2,1,:);
u=(b(1,:,:).*A(2,2)-b(2,:,:).*A(1,2))./detA;
v=(b(2,:,:).*A(1,1)-b(1,:,:).*A(2,1))./detA;
uv=cat(1,u,v);