|
| 1 | +function varargout = read_binary_or_ascii_stl(file) |
| 2 | +% STLREAD imports geometry from an STL file into MATLAB. |
| 3 | +% FV = STLREAD(FILENAME) imports triangular faces from the ASCII or binary |
| 4 | +% STL file idicated by FILENAME, and returns the patch struct FV, with fields |
| 5 | +% 'faces' and 'vertices'. |
| 6 | +% |
| 7 | +% [F,V] = STLREAD(FILENAME) returns the faces F and vertices V separately. |
| 8 | +% |
| 9 | +% [F,V,N] = STLREAD(FILENAME) also returns the face normal vectors. |
| 10 | +% |
| 11 | +% The faces and vertices are arranged in the format used by the PATCH plot |
| 12 | +% object. |
| 13 | + |
| 14 | +% Copyright 2011 The MathWorks, Inc. |
| 15 | + |
| 16 | + if ~exist(file,'file') |
| 17 | + error(['File ''%s'' not found. If the file is not on MATLAB''s path' ... |
| 18 | + ', be sure to specify the full path to the file.'], file); |
| 19 | + end |
| 20 | + |
| 21 | + fid = fopen(file,'r'); |
| 22 | + if ~isempty(ferror(fid)) |
| 23 | + error(lasterror); %#ok |
| 24 | + end |
| 25 | + |
| 26 | + M = fread(fid,inf,'uint8=>uint8'); |
| 27 | + fclose(fid); |
| 28 | + |
| 29 | + [f,v,n] = stlbinary(M); |
| 30 | + %if( isbinary(M) ) % This may not be a reliable test |
| 31 | + % [f,v,n] = stlbinary(M); |
| 32 | + %else |
| 33 | + % [f,v,n] = stlascii(M); |
| 34 | + %end |
| 35 | + |
| 36 | + varargout = cell(1,nargout); |
| 37 | + switch nargout |
| 38 | + case 2 |
| 39 | + varargout{1} = f; |
| 40 | + varargout{2} = v; |
| 41 | + case 3 |
| 42 | + varargout{1} = f; |
| 43 | + varargout{2} = v; |
| 44 | + varargout{3} = n; |
| 45 | + otherwise |
| 46 | + varargout{1} = struct('faces',f,'vertices',v); |
| 47 | + end |
| 48 | + |
| 49 | +end |
| 50 | + |
| 51 | + |
| 52 | +function [F,V,N] = stlbinary(M) |
| 53 | + |
| 54 | + F = []; |
| 55 | + V = []; |
| 56 | + N = []; |
| 57 | + |
| 58 | + if length(M) < 84 |
| 59 | + error('MATLAB:stlread:incorrectFormat', ... |
| 60 | + 'Incomplete header information in binary STL file.'); |
| 61 | + end |
| 62 | + |
| 63 | + % Bytes 81-84 are an unsigned 32-bit integer specifying the number of faces |
| 64 | + % that follow. |
| 65 | + numFaces = typecast(M(81:84),'uint32'); |
| 66 | + %numFaces = double(numFaces); |
| 67 | + if numFaces == 0 |
| 68 | + warning('MATLAB:stlread:nodata','No data in STL file.'); |
| 69 | + return |
| 70 | + end |
| 71 | + |
| 72 | + T = M(85:end); |
| 73 | + F = NaN(numFaces,3); |
| 74 | + V = NaN(3*numFaces,3); |
| 75 | + N = NaN(numFaces,3); |
| 76 | + |
| 77 | + numRead = 0; |
| 78 | + while numRead < numFaces |
| 79 | + % Each facet is 50 bytes |
| 80 | + % - Three single precision values specifying the face normal vector |
| 81 | + % - Three single precision values specifying the first vertex (XYZ) |
| 82 | + % - Three single precision values specifying the second vertex (XYZ) |
| 83 | + % - Three single precision values specifying the third vertex (XYZ) |
| 84 | + % - Two unused bytes |
| 85 | + i1 = 50 * numRead + 1; |
| 86 | + i2 = i1 + 50 - 1; |
| 87 | + facet = T(i1:i2)'; |
| 88 | + |
| 89 | + n = typecast(facet(1:12),'single'); |
| 90 | + v1 = typecast(facet(13:24),'single'); |
| 91 | + v2 = typecast(facet(25:36),'single'); |
| 92 | + v3 = typecast(facet(37:48),'single'); |
| 93 | + |
| 94 | + n = double(n); |
| 95 | + v = double([v1; v2; v3]); |
| 96 | + |
| 97 | + % Figure out where to fit these new vertices, and the face, in the |
| 98 | + % larger F and V collections. |
| 99 | + fInd = numRead + 1; |
| 100 | + vInd1 = 3 * (fInd - 1) + 1; |
| 101 | + vInd2 = vInd1 + 3 - 1; |
| 102 | + |
| 103 | + V(vInd1:vInd2,:) = v; |
| 104 | + F(fInd,:) = vInd1:vInd2; |
| 105 | + N(fInd,:) = n; |
| 106 | + |
| 107 | + numRead = numRead + 1; |
| 108 | + end |
| 109 | + |
| 110 | +end |
| 111 | + |
| 112 | + |
| 113 | +function [F,V,N] = stlascii(M) |
| 114 | + warning('MATLAB:stlread:ascii','ASCII STL files currently not supported.'); |
| 115 | + F = []; |
| 116 | + V = []; |
| 117 | + N = []; |
| 118 | +end |
| 119 | + |
| 120 | +% TODO: Change the testing criteria! Some binary STL files still begin with |
| 121 | +% 'solid'. |
| 122 | +function tf = isbinary(A) |
| 123 | +% ISBINARY uses the first line of an STL file to identify its format. |
| 124 | + if isempty(A) || length(A) < 5 |
| 125 | + error('MATLAB:stlread:incorrectFormat', ... |
| 126 | + 'File does not appear to be an ASCII or binary STL file.'); |
| 127 | + end |
| 128 | + if strcmpi('solid',char(A(1:5)')) |
| 129 | + tf = false; % ASCII |
| 130 | + else |
| 131 | + tf = true; % Binary |
| 132 | + end |
| 133 | +end |
| 134 | + |
| 135 | + |
0 commit comments