elec_fit_sphere.m

来自「Matlab下的EEG处理程序库」· M 代码 · 共 103 行

M
103
字号
function [r,x,y,z] = elec_fit_sphere(X,Y,Z,xo,yo,zo,estim)
% ELEC_FIT_SPHERE - find radius of sphere and closest spherical points to XYZ
%
% Useage: [r,x,y,z] = elec_fit_sphere(X,Y,Z,xo,yo,zo)
%
% Notes:    The general formula for a sphere, with radius r is given by:
%
%           (x - xo)^2  +  (y - yo)^2  +  (z - zo)^2  =  r^2
%
%           This function takes arguments for cartesian co-ordinates
%           of X,Y,Z (assume Z > 0) and the center of the sphere (xo,yo,zo).
%           If (xo,yo,zo) are not provided, they are assumed (0,0,0).
%
%           Returns values are the radius 'r' and the (x,y,z) Cartesian
%           co-ordinates for the fitted sphere.
%
%           See also, elec_proj_sph.m
%

% $Revision: 1.2 $ $Date: 2003/03/02 03:20:44 $

% Licence:  GNU GPL, no implied or express warranties
% History:  06/01   Darren.Weber@flinders.edu.au
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    % initialise centroid, unless input parameters defined
    if ~exist('xo','var') xo = 0; else, if isempty(xo) xo = 0; end, end
    if ~exist('yo','var') yo = 0; else, if isempty(yo) yo = 0; end, end
    if ~exist('zo','var') zo = 0; else, if isempty(zo) zo = 0; end, end
    
    % The data is assumed a rough hemisphere.
    % To fit to a sphere, we duplicate first, with negative Z.

    Zmin = min(Z); Z = Z + ( 0 - Zmin ); % translate Z so min(Z) = zero
                                         % also used below to recalc Z
    X2 = [X;X];
    Y2 = [Y;Y];
    Z2 = [Z;-Z];

    % Initialise r0 as a rough guess at the sphere radius
    rX = (max(X2) - min(X2)) / 2;
    rY = (max(Y2) - min(Y2)) / 2;
    rZ = (max(Z2) - min(Z2)) / 2;
    r0 = mean([ rX rY rZ ]);
    
    if ~exist('estim','var') estim = 1; 
    else, if isempty(estim) estim = 1; end, end
    
    if estim ==1, 
        fprintf('\n%s%f\n', 'Initial spherical radius   = ', r0); end

    % perform least squares estimate of spherical radius (r)
    options = optimset('fminsearch');
    [r,fval,exitflag,output] = fminsearch('elec_fit_sphere_optim',...
                               r0, options, X2, Y2, Z2, xo, yo, zo);
    %fprintf('\n%s%f\n', 'Iterations = ', output.iterations);
    %fprintf('\n%s%d\n', 'Exit = ', exitflag);

    if estim ==1,
        fprintf('%s%f\n',   'Estimated spherical radius = ', r); end
    

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Fit all X,Y,Z to sphere
%
%   It'd be better to find the intersection of the line from (xo,yo,zo) 
%   to (x,y,z) intersecting the sphere:
%
%   (sX,sY,sZ) where s = 1 / (X/r)^2 + (Y/r)^2 + (Z/r)^2
%
%   Instead, this routine generates points on the sphere 
%   and then locates the closest of these to each (x,y,z).

    [Xs,Ys,Zs] = elec_sphere_points(40,80,r);
    
    % For each given X,Y,Z point, locate the nearest Xs,Ys,Zs.

    x = zeros(size(X)); y = zeros(size(Y)); z = zeros(size(Z));

    for s = 1:length(X)

        xs = X(s);  ys = Y(s);  zs = Z(s);  % Get original values
        
        % Generate matrix of linear distances between point (X,Y,Z)
        % and all points on the sphere (Xs,Ys,Zs).  Could be arc
        % length, but doesn't matter here.
        d = sqrt( (Xs-xs).^2 + (Ys-ys).^2 + (Zs-zs).^2 );
        m = min(min(d));
        
        index = find (d <= m); i = index(1);
        
        if isfinite(Xs(i)) x(s) = Xs(i); 
        else fprintf('\n\aWarning: Xs(i) is NaN: %d', Xs(i)); end
        if isfinite(Ys(i)) y(s) = Ys(i); 
        else fprintf('\n\aWarning: Ys(i) is NaN: %d', Ys(i)); end
        if isfinite(Zs(i)) z(s) = Zs(i); 
        else fprintf('\n\aWarning: Zs(i) is NaN: %d', Zs(i)); end

    end
    z = z + Zmin;    % restore z to original height
    Zs = Zs + Zmin;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?