Home > bioelectromagnetism > sphere_tri.m

sphere_tri

PURPOSE ^

sphere_tri - generate a triangle mesh approximating a sphere

SYNOPSIS ^

function [FV] = sphere_tri(shape,maxlevel,r,winding)

DESCRIPTION ^

 sphere_tri - generate a triangle mesh approximating a sphere
 
 Usage: FV = sphere_tri(shape,Nrecurse,r,winding)
 
   shape is a string, either of the following:
   'ico'   starts with icosahedron (most even, default)
   'oct'   starts with octahedron
   'tetra' starts with tetrahedron (least even)

   Nrecurse is int >= 0, setting the recursions (default 0)

   r is the radius of the sphere (default 1)

   winding is 0 for clockwise, 1 for counterclockwise (default 0).  The
   matlab patch command gives outward surface normals for clockwise
   order of vertices in the faces (viewed from outside the surface).

   FV has fields FV.vertices and FV.faces.  The vertices 
   are listed in clockwise order in FV.faces, as viewed 
   from the outside in a RHS coordinate system.
 
 The function uses recursive subdivision.  The first
 approximation is an platonic solid, either an  icosahedron,
 octahedron or a tetrahedron.  Each level of refinement 
 subdivides each triangle face by a factor of 4 (see also
 mesh_refine).  At each refinement, the vertices are
 projected to the sphere surface (see sphere_project).

 A recursion level of 3 or 4 is a good sphere surface, if
 gouraud shading is used for rendering.

 The returned struct can be used in the patch command, eg:

 % create and plot, vertices: [2562x3] and faces: [5120x3]
 FV = sphere_tri('ico',4,1);
 lighting phong; shading interp; figure;
 patch('vertices',FV.vertices,'faces',FV.faces,...
       'facecolor',[1 0 0],'edgecolor',[.2 .2 .6]);
 axis off; camlight infinite; camproj('perspective');

 See also: mesh_refine, sphere_project

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [FV] = sphere_tri(shape,maxlevel,r,winding)
0002 
0003 % sphere_tri - generate a triangle mesh approximating a sphere
0004 %
0005 % Usage: FV = sphere_tri(shape,Nrecurse,r,winding)
0006 %
0007 %   shape is a string, either of the following:
0008 %   'ico'   starts with icosahedron (most even, default)
0009 %   'oct'   starts with octahedron
0010 %   'tetra' starts with tetrahedron (least even)
0011 %
0012 %   Nrecurse is int >= 0, setting the recursions (default 0)
0013 %
0014 %   r is the radius of the sphere (default 1)
0015 %
0016 %   winding is 0 for clockwise, 1 for counterclockwise (default 0).  The
0017 %   matlab patch command gives outward surface normals for clockwise
0018 %   order of vertices in the faces (viewed from outside the surface).
0019 %
0020 %   FV has fields FV.vertices and FV.faces.  The vertices
0021 %   are listed in clockwise order in FV.faces, as viewed
0022 %   from the outside in a RHS coordinate system.
0023 %
0024 % The function uses recursive subdivision.  The first
0025 % approximation is an platonic solid, either an  icosahedron,
0026 % octahedron or a tetrahedron.  Each level of refinement
0027 % subdivides each triangle face by a factor of 4 (see also
0028 % mesh_refine).  At each refinement, the vertices are
0029 % projected to the sphere surface (see sphere_project).
0030 %
0031 % A recursion level of 3 or 4 is a good sphere surface, if
0032 % gouraud shading is used for rendering.
0033 %
0034 % The returned struct can be used in the patch command, eg:
0035 %
0036 % % create and plot, vertices: [2562x3] and faces: [5120x3]
0037 % FV = sphere_tri('ico',4,1);
0038 % lighting phong; shading interp; figure;
0039 % patch('vertices',FV.vertices,'faces',FV.faces,...
0040 %       'facecolor',[1 0 0],'edgecolor',[.2 .2 .6]);
0041 % axis off; camlight infinite; camproj('perspective');
0042 %
0043 % See also: mesh_refine, sphere_project
0044 %
0045 
0046 
0047 
0048 % $Revision: 1.2 $ $Date: 2005/07/20 23:07:03 $
0049 
0050 % Licence:  GNU GPL, no implied or express warranties
0051 % Jon Leech (leech @ cs.unc.edu) 3/24/89
0052 % icosahedral code added by Jim Buddenhagen (jb1556@daditz.sbc.com) 5/93
0053 % 06/2002, adapted from c to matlab by Darren.Weber_at_radiology.ucsf.edu
0054 % 05/2004, reorder of the faces for the 'ico' surface so they are indeed
0055 % clockwise!  Now the surface normals are directed outward.  Also reset the
0056 % default recursions to zero, so we can get out just the platonic solids.
0057 %
0058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0059 
0060 eegversion = '$Revision: 1.2 $';
0061 fprintf('SPHERE_TRI [v %s]\n',eegversion(11:15)); tic
0062 
0063 if ~exist('shape','var') || isempty(shape),
0064     shape = 'ico';
0065 end
0066 fprintf('...creating sphere tesselation based on %s\n',shape);
0067 
0068 % default maximum subdivision level
0069 if ~exist('maxlevel','var') || isempty(maxlevel) || maxlevel < 0,
0070     maxlevel = 0;
0071 end
0072 
0073 % default radius
0074 if ~exist('r','var') || isempty(r),
0075     r = 1;
0076 end
0077 
0078 if ~exist('winding','var') || isempty(winding),
0079     winding = 0;
0080 end
0081 
0082 
0083 % -----------------
0084 % define the starting shapes
0085 
0086 shape = lower(shape);
0087 
0088 switch shape,
0089 case 'tetra',
0090     
0091     % Vertices of a tetrahedron
0092     sqrt_3 = 0.5773502692;
0093     
0094     tetra.v = [  sqrt_3,  sqrt_3,  sqrt_3 ;   % +X, +Y, +Z  - PPP
0095                 -sqrt_3, -sqrt_3,  sqrt_3 ;   % -X, -Y, +Z  - MMP
0096                 -sqrt_3,  sqrt_3, -sqrt_3 ;   % -X, +Y, -Z  - MPM
0097                  sqrt_3, -sqrt_3, -sqrt_3 ];  % +X, -Y, -Z  - PMM
0098     
0099     % Structure describing a tetrahedron
0100     tetra.f = [ 1, 2, 3;
0101                 1, 4, 2;
0102                 3, 2, 4;
0103                 4, 1, 3 ];
0104     
0105     FV.vertices = tetra.v;
0106     FV.faces    = tetra.f;
0107     
0108 case 'oct',
0109     
0110     % Six equidistant points lying on the unit sphere
0111     oct.v = [  1,  0,  0 ;  %  X
0112               -1,  0,  0 ;     % -X
0113                0,  1,  0 ;  %  Y
0114                0, -1,  0 ;     % -Y
0115                0,  0,  1 ;     %  Z
0116                0,  0, -1 ];    % -Z
0117     
0118     % Join vertices to create a unit octahedron
0119     oct.f = [ 1 5 3 ;    %  X  Z  Y  -  First the top half
0120               3 5 2 ;    %  Y  Z -X
0121               2 5 4 ;    % -X  Z -Y
0122               4 5 1 ;    % -Y  Z  X
0123               1 3 6 ;    %  X  Y -Z  -  Now the bottom half
0124               3 2 6 ;    %  Y  Z -Z
0125               2 4 6 ;    % -X  Z -Z
0126               4 1 6 ];   % -Y  Z -Z
0127     
0128     FV.vertices = oct.v;
0129     FV.faces    = oct.f;
0130     
0131 case 'ico',
0132     
0133     % Twelve vertices of icosahedron on unit sphere
0134     tau = 0.8506508084; % t=(1+sqrt(5))/2, tau=t/sqrt(1+t^2)
0135     one = 0.5257311121; % one=1/sqrt(1+t^2) , unit sphere
0136     
0137     ico.v( 1,:) = [  tau,  one,    0 ]; % ZA
0138     ico.v( 2,:) = [ -tau,  one,    0 ]; % ZB
0139     ico.v( 3,:) = [ -tau, -one,    0 ]; % ZC
0140     ico.v( 4,:) = [  tau, -one,    0 ]; % ZD
0141     ico.v( 5,:) = [  one,   0 ,  tau ]; % YA
0142     ico.v( 6,:) = [  one,   0 , -tau ]; % YB
0143     ico.v( 7,:) = [ -one,   0 , -tau ]; % YC
0144     ico.v( 8,:) = [ -one,   0 ,  tau ]; % YD
0145     ico.v( 9,:) = [   0 ,  tau,  one ]; % XA
0146     ico.v(10,:) = [   0 , -tau,  one ]; % XB
0147     ico.v(11,:) = [   0 , -tau, -one ]; % XC
0148     ico.v(12,:) = [   0 ,  tau, -one ]; % XD
0149     
0150     % Structure for unit icosahedron
0151     ico.f = [  5,  8,  9 ;
0152                5, 10,  8 ;
0153                6, 12,  7 ;
0154                6,  7, 11 ;
0155                1,  4,  5 ;
0156                1,  6,  4 ;
0157                3,  2,  8 ;
0158                3,  7,  2 ;
0159                9, 12,  1 ;
0160                9,  2, 12 ;
0161               10,  4, 11 ;
0162               10, 11,  3 ;
0163                9,  1,  5 ;
0164               12,  6,  1 ;
0165                5,  4, 10 ;
0166                6, 11,  4 ;
0167                8,  2,  9 ;
0168                7, 12,  2 ;
0169                8, 10,  3 ;
0170                7,  3, 11 ];
0171     
0172     FV.vertices = ico.v;
0173     FV.faces    = ico.f;
0174 end
0175 
0176 
0177 % -----------------
0178 % refine the starting shapes with subdivisions
0179 if maxlevel,
0180     
0181     % Subdivide each starting triangle (maxlevel) times
0182     for level = 1:maxlevel,
0183         
0184         % Subdivide each triangle and normalize the new points thus
0185         % generated to lie on the surface of a sphere radius r.
0186         FV = mesh_refine_tri4(FV);
0187         FV.vertices = sphere_project(FV.vertices,r);
0188         
0189         % An alternative might be to define a min distance
0190         % between vertices and recurse or use fminsearch
0191         
0192     end
0193 end
0194 
0195 if winding,
0196     fprintf('...returning counterclockwise vertex order (viewed from outside)\n');
0197     FV.faces = FV.faces(:,[1 3 2]);
0198 else
0199     fprintf('...returning clockwise vertex order (viewed from outside)\n');
0200 end
0201 
0202 t=toc; fprintf('...done (%6.2f sec)\n\n',t);
0203 
0204 return

Generated on Mon 15-Aug-2005 15:36:19 by m2html © 2003