1
+ function varargout = STL_Import(filename ,mode )
2
+ % STL_Import is a tool designed to import into MATLAB both binary and ASCII STL files.
3
+ %
4
+ % This scprit is mainly a collage betwwen file axchange fileid 22409 and 3642, plus
5
+ % some other features that can be considered new on FEX.
6
+ %
7
+ % SYNOPSIS:
8
+ %
9
+ %
10
+ % %mode 1 (default)
11
+ % [p,t,tnorm]=STL_Import(filename,mode)
12
+ %
13
+ % %mode 2
14
+ % [v,tnorm])=STL_Import(filename,mode)
15
+ %
16
+ %
17
+ % INPUT:
18
+ %
19
+ % filename: string representing the name fo the file
20
+ %
21
+ % mode:
22
+ %
23
+ %
24
+ % mode=1 (if omitted is automatically set to one)
25
+ %
26
+ % set the the output to:
27
+ %
28
+ % output=[p,t,tnorm]
29
+ %
30
+ % where
31
+ %
32
+ % p=points (unique) of the model nx3 array
33
+
34
+ % t=triangles indexes of the model
35
+
36
+ % tnorm= normals of triangles
37
+ %
38
+
39
+ % mode=2
40
+ %
41
+ % set the the output to:
42
+ %
43
+ % output=[v,tnorm]
44
+ %
45
+ % where
46
+ %
47
+ % v= vertex of the model(not unique points) of the model nx3 array. Each
48
+ % trhee points we have a triagnle in consecutive order.
49
+
50
+ % tnorm= normals of triangles
51
+ %
52
+ % EXAMPLES:
53
+ %
54
+ % [p,t,tnorm]=STL_Import('link1.stl',1);
55
+ % [pv,tnorm]=STL_Import('link1.stl',2);
56
+ %
57
+ %
58
+ % Visit:
59
+ %
60
+ % http://giaccariluigi.altervista.org/blog/
61
+ %
62
+ % Author: Giaccari Luigi ([email protected] )
63
+
64
+
65
+
66
+ if nargin < 2
67
+ mode= 1 ;% default value
68
+ end
69
+
70
+
71
+ if ~(mode == 1 || mode == 2 )
72
+ error(' invalid mode' )
73
+ end
74
+
75
+ if nargout < 3 && mode == 1
76
+ error(' invalid input number /mode setting' )
77
+ end
78
+ if nargout > 2 && mode == 2
79
+ error(' invalid input number /mode setting' )
80
+ end
81
+
82
+
83
+ % open file
84
+ fid= fopen(filename , ' r' ); % Open the file, assumes STL ASCII format.
85
+ if fid == - 1
86
+ error(' File could not be opened, check name or path.' )
87
+ end
88
+
89
+
90
+ M = fread(fid ,inf ,' uint8=>uint8' );
91
+ fclose(fid );
92
+
93
+ if ( isbinary(M ) )
94
+ [v ,tnorm ]=ImportSTL_binary(M );
95
+
96
+ else
97
+ clear M ;
98
+ [v ,tnorm ]=ImportSTL_ASCII(filename );
99
+
100
+ end
101
+
102
+ clear M
103
+
104
+ varargout = cell(1 ,nargout );
105
+ switch mode
106
+ case 1
107
+ [p ,t ]=fv2pt(v ,length(v )/3 );% gets points and triangles
108
+
109
+ varargout{1 } = p ;
110
+ varargout{2 } = t ;
111
+ varargout{3 } = tnorm ;
112
+ case 2
113
+ varargout{1 } = v ;
114
+ varargout{2 } = tnorm ;
115
+ end
116
+ end
117
+
118
+
119
+
120
+ function [v ,tnorm ]=ImportSTL_ASCII(filename )
121
+
122
+ % counting the number of vertex
123
+ vnum= 0 ;
124
+ fid= fopen(filename , ' r' ); % Open the file, assumes STL ASCII format.
125
+ while feof(fid ) == 0 % test for end of file, if not then do stuff
126
+ tline = fgetl(fid ); % reads a line of data from file.
127
+ fword = sscanf(tline , ' %s ' ); % make the line a character string
128
+ if strncmpi(fword , ' v' ,1 ) ; % Checking if a "V"ertex line, as "V" is 1st char.
129
+ vnum = vnum + 1 ; % If a V we count the # of V's
130
+ end
131
+ end
132
+ numt= ceil(vnum / 3 );% triangles number equals vertex number/3
133
+
134
+ tnorm= zeros(numt ,3 );% preallocate for normals
135
+ v= zeros(vnum ,3 );% not unique vertex
136
+
137
+ c= 0 ;% vertex counter
138
+ fnum= 0 ;
139
+ fid= fopen(filename , ' r' ); % REOpen the file
140
+ while feof(fid ) == 0 % test for end of file, if not then do stuff
141
+ tline = fgetl(fid ); % reads a line of data from file.
142
+ fword = sscanf(tline , ' %s ' ); % make the line a character string
143
+
144
+ %% Check vertex
145
+ if strncmpi(fword , ' v' ,1 ) ; % Checking if a "V"ertex line, as "V" is 1st char.
146
+ c = c + 1 ; % If a V we count the # of V's
147
+ v(c ,: ) = sscanf(tline , ' %*s %f %f %f ' ); % & if a V, get the XYZ data of it.
148
+
149
+ %% Check facet normal
150
+ elseif strncmpi(fword , ' f' ,1 ) ; % Checking if a "V"ertex line, as "V" is 1st char.
151
+ fnum = fnum + 1 ; % If a V we count the # of V's
152
+ tnorm(fnum ,: ) = sscanf(tline , ' %*s %*s %f %f %f ' ); % & if a V, get the XYZ data of it.
153
+
154
+ % %% Check for color
155
+ % elseif strncmpi(fword, 'c',1) ; % Checking if a "C"olor line, as "C" is 1st char.
156
+ % VColor = sscanf(tline, '%*s %f %f %f'); % & if a C, get the RGB color data of the face.
157
+ % % Keep this color, until the next color is used.
158
+
159
+ end
160
+
161
+ end
162
+ end
163
+
164
+
165
+ function [p ,t ]=fv2pt(v ,fnum )
166
+
167
+ % gets points and triangle indexes given vertex and facet number
168
+
169
+ c= size(v ,1 );
170
+
171
+ % triangles with vertex id data
172
+ t= zeros(3 ,fnum );
173
+ t(: )=1 : c ;
174
+
175
+
176
+ % now we have to keep unique points fro vertex
177
+ [p ,i ,j ]=unique(v ,' rows' ); % now v=p(j) p(i)=v;
178
+ t(: )=j(t(: ));
179
+ t= t ' ;
180
+
181
+ end
182
+
183
+ %
184
+
185
+
186
+ function tf = isbinary(A )
187
+ % ISBINARY determines if an STL file is binary or ASCII.
188
+
189
+ % Look for the string 'endsolid' near the end of the file
190
+ if isempty(A ) || length(A ) < 16
191
+ error(' MATLAB:stlread:incorrectFormat' , ...
192
+ ' File does not appear to be an ASCII or binary STL file.' );
193
+ end
194
+
195
+ % Read final 16 characters of M
196
+ i2 = length(A );
197
+ i1 = i2 - 100 ;% 100 empirical value
198
+ str = char( A(i1 : i2 )' );
199
+
200
+ k = strfind(lower(str ), ' endsolid' );
201
+ if ~isempty(k )
202
+ tf = false ; % ASCII
203
+ else
204
+ tf = true ; % Binary
205
+ end
206
+ end
207
+
208
+
209
+ function [V ,N ]=ImportSTL_binary(M )
210
+
211
+
212
+
213
+ if length(M ) < 84
214
+ error(' MATLAB:stlread:incorrectFormat' , ...
215
+ ' Incomplete header information in binary STL file.' );
216
+ end
217
+
218
+ % Bytes 81-84 are an unsigned 32-bit integer specifying the number of faces
219
+ % that follow.
220
+ numFaces = typecast(M(81 : 84 ),' uint32' );
221
+ % numFaces = double(numFaces);
222
+ if numFaces == 0
223
+ warning(' MATLAB:stlread:nodata' ,' No data in STL file.' );
224
+ return
225
+ end
226
+
227
+ T = M(85 : end );
228
+
229
+ V = NaN(3 * numFaces ,3 );
230
+ N = NaN(numFaces ,3 );
231
+
232
+ numRead = 0 ;
233
+ while numRead < numFaces
234
+ % Each facet is 50 bytes
235
+ % - Three single precision values specifying the face normal vector
236
+ % - Three single precision values specifying the first vertex (XYZ)
237
+ % - Three single precision values specifying the second vertex (XYZ)
238
+ % - Three single precision values specifying the third vertex (XYZ)
239
+ % - Two unused bytes
240
+ i1 = 50 * numRead + 1 ;
241
+ i2 = i1 + 50 - 1 ;
242
+ facet = T(i1 : i2 )' ;
243
+
244
+ n = typecast(facet(1 : 12 ),' single' );
245
+ v1 = typecast(facet(13 : 24 ),' single' );
246
+ v2 = typecast(facet(25 : 36 ),' single' );
247
+ v3 = typecast(facet(37 : 48 ),' single' );
248
+
249
+ n = double(n );
250
+ v = double([v1 ; v2 ; v3 ]);
251
+
252
+ % Figure out where to fit these new vertices, and the face, in the
253
+ % larger F and V collections.
254
+ fInd = numRead + 1 ;
255
+ vInd1 = 3 * (fInd - 1 ) + 1 ;
256
+ vInd2 = vInd1 + 3 - 1 ;
257
+
258
+ V(vInd1 : vInd2 ,: ) = v ;
259
+ N(fInd ,: ) = n ;
260
+
261
+ numRead = numRead + 1 ;
262
+ end
263
+
264
+ end
0 commit comments