READ_stl

PURPOSE ^

READ_stlascii Read mesh data in the form of an <*.stl> file

SYNOPSIS ^

function [coordVERTICES,varargout] = READ_stl(stlFILENAME,varargin)

DESCRIPTION ^

 READ_stlascii  Read mesh data in the form of an <*.stl> file
==========================================================================
 FILENAME:          READ_stl.m
 AUTHOR:            Adam H. Aitkenhead
 INSTITUTION:       The Christie NHS Foundation Trust
 CONTACT:           adam.aitkenhead@physics.cr.man.ac.uk
 DATE:              29th March 2010
 PURPOSE:           Read mesh data in the form of an <*.stl> file.

 USAGE:

     [coordVERTICES,coordNORMALS,stlNAME] = READ_stl(stlFILENAME,stlFORMAT)

 INPUT PARAMETERS:

     stlFILENAME   - String - Mandatory - The filename of the STL file.

     stlFORMAT     - String - Optional  - The format of the STL file:
                                        'ascii' or 'binary'

 OUTPUT PARAMETERS:

     coordVERTICES - Nx3x3 array - Mandatory
                                 - An array defining the vertex positions
                                   for each of the N facets, with: 
                                   1 row for each facet
                                   3 cols for the x,y,z coordinates
                                   3 pages for the three vertices

     coordNORMALS  - Nx3 array   - Optional
                                 - An array defining the normal vector for
                                   each of the N facets, with: 
                                   1 row for each facet
                                   3 cols for the x,y,z components of the vector

     stlNAME       - String      - Optional  - The name of the STL object.

==========================================================================

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [coordVERTICES,varargout] = READ_stl(stlFILENAME,varargin)
0002 % READ_stlascii  Read mesh data in the form of an <*.stl> file
0003 %==========================================================================
0004 % FILENAME:          READ_stl.m
0005 % AUTHOR:            Adam H. Aitkenhead
0006 % INSTITUTION:       The Christie NHS Foundation Trust
0007 % CONTACT:           adam.aitkenhead@physics.cr.man.ac.uk
0008 % DATE:              29th March 2010
0009 % PURPOSE:           Read mesh data in the form of an <*.stl> file.
0010 %
0011 % USAGE:
0012 %
0013 %     [coordVERTICES,coordNORMALS,stlNAME] = READ_stl(stlFILENAME,stlFORMAT)
0014 %
0015 % INPUT PARAMETERS:
0016 %
0017 %     stlFILENAME   - String - Mandatory - The filename of the STL file.
0018 %
0019 %     stlFORMAT     - String - Optional  - The format of the STL file:
0020 %                                        'ascii' or 'binary'
0021 %
0022 % OUTPUT PARAMETERS:
0023 %
0024 %     coordVERTICES - Nx3x3 array - Mandatory
0025 %                                 - An array defining the vertex positions
0026 %                                   for each of the N facets, with:
0027 %                                   1 row for each facet
0028 %                                   3 cols for the x,y,z coordinates
0029 %                                   3 pages for the three vertices
0030 %
0031 %     coordNORMALS  - Nx3 array   - Optional
0032 %                                 - An array defining the normal vector for
0033 %                                   each of the N facets, with:
0034 %                                   1 row for each facet
0035 %                                   3 cols for the x,y,z components of the vector
0036 %
0037 %     stlNAME       - String      - Optional  - The name of the STL object.
0038 %
0039 %==========================================================================
0040 
0041 %==========================================================================
0042 % VERSION  USER  CHANGES
0043 % -------  ----  -------
0044 % 100329   AHA   Original version
0045 % 100513   AHA   Totally reworked the code.  Now use textscan to read the
0046 %                file all at once, rather than one line at a time with
0047 %                fgetl.  Major speed improvment.
0048 % 100623   AHA   Combined code which reads ascii STLS and code which reads
0049 %                binary STLs into a single function.
0050 % 101126   AHA   Small change to binary read code:  Now use fread instead
0051 %                of fseek.  Gives large speed increase.
0052 %==========================================================================
0053 
0054 %==========================================================================
0055 % STL ascii file format
0056 %======================
0057 % ASCII STL files have the following structure.  Technically each facet
0058 % could be any 2D shape, but in practice only triangular facets tend to be
0059 % used.  The present code ONLY works for meshes composed of triangular
0060 % facets.
0061 %
0062 % solid object_name
0063 % facet normal x y z
0064 %   outer loop
0065 %     vertex x y z
0066 %     vertex x y z
0067 %     vertex x y z
0068 %   endloop
0069 % endfacet
0070 %
0071 % <Repeat for all facets...>
0072 %
0073 % endsolid object_name
0074 %==========================================================================
0075 
0076 %==========================================================================
0077 % STL binary file format
0078 %=======================
0079 % Binary STL files have an 84 byte header followed by 50-byte records, each
0080 % describing a single facet of the mesh.  Technically each facet could be
0081 % any 2D shape, but that would screw up the 50-byte-per-facet structure, so
0082 % in practice only triangular facets are used.  The present code ONLY works
0083 % for meshes composed of triangular facets.
0084 %
0085 % HEADER:
0086 % 80 bytes:  Header text
0087 % 4 bytes:   (int) The number of facets in the STL mesh
0088 %
0089 % DATA:
0090 % 4 bytes:  (float) normal x
0091 % 4 bytes:  (float) normal y
0092 % 4 bytes:  (float) normal z
0093 % 4 bytes:  (float) vertex1 x
0094 % 4 bytes:  (float) vertex1 y
0095 % 4 bytes:  (float) vertex1 z
0096 % 4 bytes:  (float) vertex2 x
0097 % 4 bytes:  (float) vertex2 y
0098 % 4 bytes:  (float) vertex2 z
0099 % 4 bytes:  (float) vertex3 x
0100 % 4 bytes:  (float) vertex3 y
0101 % 4 bytes:  (float) vertex3 z
0102 % 2 bytes:  Padding to make the data for each facet 50-bytes in length
0103 %   ...and repeat for next facet...
0104 %==========================================================================
0105 
0106 if nargin==2
0107   stlFORMAT = lower(varargin{1});
0108 else
0109   stlFORMAT = 'auto';
0110 end
0111 
0112 %If necessary, identify whether the STL is ascii or binary:
0113 if strcmp(stlFORMAT,'ascii')==0 && strcmp(stlFORMAT,'binary')==0
0114   stlFORMAT = IDENTIFY_stl_format(stlFILENAME);
0115 end
0116 
0117 %Load the STL file:
0118 if strcmp(stlFORMAT,'ascii')
0119   [coordVERTICES,coordNORMALS,stlNAME] = READ_stlascii(stlFILENAME);
0120 elseif strcmp(stlFORMAT,'binary')
0121   [coordVERTICES,coordNORMALS] = READ_stlbinary(stlFILENAME);
0122   stlNAME = 'unnamed_object';
0123 end %if
0124 
0125 %Prepare the output arguments
0126 if nargout == 2
0127   varargout(1) = {coordNORMALS};
0128 elseif nargout == 3
0129   varargout(1) = {coordNORMALS};
0130   varargout(2) = {stlNAME};
0131 end
0132 
0133 end %function
0134 
0135 
0136 
0137 %==========================================================================
0138 function [stlFORMAT] = IDENTIFY_stl_format(stlFILENAME)
0139 % IDENTIFY_stl_format  Test whether an stl file is ascii or binary
0140 
0141 % Open the file:
0142 fidIN = fopen(stlFILENAME);
0143 
0144 % Check the file size first, since binary files MUST have a size of 84+(50*n)
0145 fseek(fidIN,0,1);         % Go to the end of the file
0146 fidSIZE = ftell(fidIN);   % Check the size of the file
0147 
0148 if rem(fidSIZE-84,50) > 0
0149     
0150   stlFORMAT = 'ascii';
0151 
0152 else
0153 
0154   % Files with a size of 84+(50*n), might be either ascii or binary...
0155     
0156   % Read first 80 characters of the file.
0157   % For an ASCII file, the data should begin immediately (give or take a few
0158   % blank lines or spaces) and the first word must be 'solid'.
0159   % For a binary file, the first 80 characters contains the header.
0160   % It is bad practice to begin the header of a binary file with the word
0161   % 'solid', so it can be used to identify whether the file is ASCII or
0162   % binary.
0163   fseek(fidIN,0,-1);        % Go to the start of the file
0164   firsteighty = char(fread(fidIN,80,'uchar')');
0165 
0166   % Trim leading and trailing spaces:
0167   firsteighty = strtrim(firsteighty);
0168 
0169   % Take the first five remaining characters, and check if these are 'solid':
0170   firstfive = firsteighty(1:min(5,length(firsteighty)));
0171 
0172   % Double check by reading the last 80 characters of the file.
0173   % For an ASCII file, the data should end (give or take a few
0174   % blank lines or spaces) with 'endsolid <object_name>'.
0175   % If the last 80 characters contains the word 'endsolid' then this
0176   % confirms that the file is indeed ASCII.
0177   if strcmp(firstfive,'solid')
0178   
0179     fseek(fidIN,-80,1);     % Go to the end of the file minus 80 characters
0180     lasteighty = char(fread(fidIN,80,'uchar')');
0181   
0182     if findstr(lasteighty,'endsolid')
0183       stlFORMAT = 'ascii';
0184     else
0185       stlFORMAT = 'binary';
0186     end
0187   
0188   else
0189     stlFORMAT = 'binary';
0190   end
0191   
0192 end
0193 
0194 % Close the file
0195 fclose(fidIN);
0196 
0197 end %function
0198 %==========================================================================
0199 
0200 
0201 
0202 %==========================================================================
0203 function [coordVERTICES,coordNORMALS,stlNAME] = READ_stlascii(stlFILENAME)
0204 % READ_stlascii  Read mesh data in the form of an ascii <*.stl> file
0205 
0206 % Read the ascii STL file
0207 fidIN = fopen(stlFILENAME);
0208 fidCONTENTcell = textscan(fidIN,'%s','delimiter','\n');                  %Read all the file
0209 fidCONTENT = fidCONTENTcell{:}(logical(~strcmp(fidCONTENTcell{:},'')));  %Remove all blank lines
0210 fclose(fidIN);
0211 
0212 % Read the STL name
0213 if nargout == 3
0214   line1 = char(fidCONTENT(1));
0215   if (size(line1,2) >= 7)
0216     stlNAME = line1(7:end);
0217   else
0218     stlNAME = 'unnamed_object'; 
0219   end
0220 end
0221 
0222 % Read the vector normals
0223 if nargout >= 2
0224   stringNORMALS = char(fidCONTENT(logical(strncmp(fidCONTENT,'facet normal',12))));
0225   coordNORMALS  = str2num(stringNORMALS(:,13:end));
0226 end
0227 
0228 % Read the vertex coordinates
0229 facetTOTAL       = sum(strcmp(fidCONTENT,'endfacet'));
0230 stringVERTICES   = char(fidCONTENT(logical(strncmp(fidCONTENT,'vertex',6))));
0231 coordVERTICESall = str2num(stringVERTICES(:,7:end));
0232 cotemp           = zeros(3,facetTOTAL,3);
0233 cotemp(:)        = coordVERTICESall;
0234 coordVERTICES    = shiftdim(cotemp,1);
0235 
0236 end %function
0237 %==========================================================================
0238 
0239 
0240 
0241 %==========================================================================
0242 function [coordVERTICES,coordNORMALS] = READ_stlbinary(stlFILENAME)
0243 % READ_stlbinary  Read mesh data in the form of an binary <*.stl> file
0244 
0245 % Open the binary STL file
0246 fidIN = fopen(stlFILENAME);
0247 
0248 % Read the header
0249 fseek(fidIN,80,-1);                   % Move to the last 4 bytes of the header
0250 facetcount = fread(fidIN,1,'int32');  % Read the number of facets in the stl file
0251 
0252 % Initialise arrays into which the STL data will be loaded:
0253 coordNORMALS  = zeros(facetcount,3);
0254 coordVERTICES = zeros(facetcount,3,3);
0255 
0256 % Read the data for each facet:
0257 for loopF = 1:facetcount
0258   
0259   tempIN = fread(fidIN,3*4,'float');
0260   
0261   coordNORMALS(loopF,1:3)    = tempIN(1:3);    % x,y,z components of the facet's normal vector
0262   coordVERTICES(loopF,1:3,1) = tempIN(4:6);    % x,y,z coordinates of vertex 1
0263   coordVERTICES(loopF,1:3,2) = tempIN(7:9);    % x,y,z coordinates of vertex 2
0264   coordVERTICES(loopF,1:3,3) = tempIN(10:12);  % x,y,z coordinates of vertex 3
0265   
0266   fread(fidIN,1,'int16');   % Move to the start of the next facet.  Using fread is much quicker than using fseek(fidIN,2,0);
0267 
0268 end %for
0269 
0270 % Close the binary STL file
0271 fclose(fidIN);
0272 
0273 end %function
0274 %==========================================================================

Generated on Fri 30-Dec-2022 19:44:54 by m2html © 2005