function [ofs,gain,rotM]=ellipsoid_fit(XYZ,varargin) 

% Fit an (non)rotated ellipsoid or sphere to a set of xyz data points 

% XYZ: N(rows) x 3(cols), matrix of N data points (x,y,z) 

% optional flag f, default to 0 (fitting of rotated ellipsoid) 

x=XYZ(:,1); y=XYZ(:,2); z=XYZ(:,3); if nargin>1, f=varargin{1}; else f=0; end; 

if f==0, D=[x.*x, y.*y, z.*z, 2*x.*y,2*x.*z,2*y.*z, 2*x,2*y,2*z]; % any axes (rotated ellipsoid) 

elseif f==1, D=[x.*x, y.*y, z.*z, 2*x,2*y,2*z]; % XYZ axes (non-rotated ellipsoid) 

elseif f==2, D=[x.*x+y.*y, z.*z, 2*x,2*y,2*z]; % and radius x=y 

elseif f==3, D=[x.*x+z.*z, y.*y, 2*x,2*y,2*z]; % and radius x=z 

elseif f==4, D=[y.*y+z.*z, x.*x, 2*x,2*y,2*z]; % and radius y=z 

elseif f==5, D=[x.*x+y.*y+z.*z, 2*x,2*y,2*z]; % and radius x=y=z (sphere) 

end; 

v = (D'*D)\(D'*ones(length(x),1)); % least square fitting 

if f==0, % rotated ellipsoid 

 A = [ v(1) v(4) v(5) v(7); v(4) v(2) v(6) v(8); v(5) v(6) v(3) v(9); v(7) v(8) v(9) -1 ]; 

 ofs=-A(1:3,1:3)\[v(7);v(8);v(9)]; % offset is center of ellipsoid 

 Tmtx=eye(4); Tmtx(4,1:3)=ofs'; AT=Tmtx*A*Tmtx'; % ellipsoid translated to (0,0,0) 

 [rotM ev]=eig(AT(1:3,1:3)/-AT(4,4)); % eigenvectors (rotation) and eigenvalues (gain) 

 gain=sqrt(1./diag(ev)); % gain is radius of the ellipsoid 

else % non-rotated ellipsoid 

 if f==1, v = [ v(1) v(2) v(3) 0 0 0 v(4) v(5) v(6) ]; 

 elseif f==2, v = [ v(1) v(1) v(2) 0 0 0 v(3) v(4) v(5) ]; 

 elseif f==3, v = [ v(1) v(2) v(1) 0 0 0 v(3) v(4) v(5) ]; 

 elseif f==4, v = [ v(2) v(1) v(1) 0 0 0 v(3) v(4) v(5) ]; 

 elseif f==5, v = [ v(1) v(1) v(1) 0 0 0 v(2) v(3) v(4) ]; % sphere 

 end; 

 ofs=-(v(1:3).\v(7:9))'; % offset is center of ellipsoid 

 rotM=eye(3); % eigenvectors (rotation), identity = no rotation 

 g=1+(v(7)^2/v(1)+v(8)^2/v(2)+v(9)^2/v(3)); 

 gain=(sqrt(g./v(1:3)))'; % find radii of the ellipsoid (scale) 

end; 
