Skip to content

Commit 4d08f75

Browse files
authored
Add files via upload
1 parent cb87bbb commit 4d08f75

File tree

6 files changed

+1170
-0
lines changed

6 files changed

+1170
-0
lines changed

ImportFiles.m

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
function [Mesh1, n1, Mesh2] = ImportFiles(f1, f2, f2Transformation)
2+
% Inputs:
3+
% f1 = file 1 string (must end with .stl)
4+
% f2 = file 2 string (must end with .stl)
5+
% f2Transformation = 4x4 transformation matrix that will be applied to
6+
% Mesh2 so it is aligned with Mesh1
7+
%
8+
% Outputs:
9+
% Mesh1 = stl model stored in f1 (triangulation object)
10+
% n1 = normal vectors for each triangle in Mesh1
11+
% Mesh2 = stl model stored in f2 (triangulation object)
12+
%
13+
% STL_Import() is used so that normal vectors can be imported easily
14+
[p1, t1, n1] = STL_Import(f1,1);
15+
[p2, t2, n2] = STL_Import(f2,1);
16+
17+
% points in p2 must be transformed before mesh is created
18+
p2 = [p2 ones(1,size(p2, 1))']';
19+
p2 = f2Transformation*p2;
20+
p2 = p2';
21+
p2(:,4) = [];
22+
23+
% Mesh 1 and 2 can now be created
24+
Mesh1 = triangulation(t1, p1);
25+
Mesh2 = triangulation(t2, p2);
26+
end

RMSE.m

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function rmse = RMSE(residuals)
2+
rmse = sqrt(mean(residuals.^2));
3+
end

SCRIPT.m

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
clc; clear;
2+
%
3+
% This script requires the user to manually input file1, file2, and
4+
% f2Transformation
5+
% NOTE: scanTransformation is applied to file2
6+
7+
file1 = '<INSERT FILENAME 1>.stl';
8+
file2 = '<INSERT FILENAME 2>.stl';
9+
f2Transformation = [ 1 0 0 0
10+
0 1 0 0
11+
0 0 1 0
12+
0 0 0 1 ];
13+
14+
15+
% Mesh1 = stl model stored in file1 (triangulation object)
16+
% n1 = normal vectors for each triangle in Mesh1
17+
% Mesh2 = stl model stored in file2 (triangulation object)
18+
[Mesh1, n1, Mesh2] = ImportFiles(file1, file2, f2Transformation);
19+
20+
% residuals1 = residual values per triangle in Mesh1
21+
% residuals2 = residual values per traingle in Mesh2
22+
% distances1 = minimum distances from triangle centers in Mesh1 to surface
23+
% of Mesh2
24+
% distances2 = minimum distances from triangle centers in Mesh2 to surface
25+
% of Mesh1
26+
[residuals1, residuals2] = rDistances(Mesh1, n1, Mesh2);
27+
[distances1] = -point2trimesh('Faces', Mesh2.ConnectivityList, 'Vertices', Mesh2.Points, 'QueryPoints', incenter(Mesh1), 'Algorithm', 'parallel');
28+
[distances2] = point2trimesh('Faces', Mesh1.ConnectivityList, 'Vertices', Mesh1.Points, 'QueryPoints', incenter(Mesh2), 'Algorithm', 'parallel');
29+
30+
31+
disp('RMSE of:')
32+
rmse = RMSE(residuals1);
33+
disp(" Residuals Mesh1: " + rmse + " ")
34+
rmse = RMSE(residuals2);
35+
disp(" Residuals Mesh2: " + rmse + " ")
36+
rmse = RMSE(distances1);
37+
disp(" Distances 1: " + rmse + " ")
38+
rmse = RMSE(distances2);
39+
disp(" Distances 2: " + rmse + " ")
40+
41+
42+
figure('name', 'Residuals Mesh1')
43+
trisurf(Mesh1, residuals1,'linestyle', 'none')
44+
axis equal
45+
title('Residuals Mesh1')
46+
colorbar
47+
48+
figure('name','Residuals Mesh2')
49+
trisurf(Mesh2, residuals2,'linestyle', 'none')
50+
axis equal
51+
title('Residuals Mesh2')
52+
colorbar
53+
54+
figure('name', 'Distances 1')
55+
trisurf(Mesh1, distances1, 'linestyle', 'none')
56+
axis equal
57+
title('Distances 1')
58+
colorbar
59+
60+
figure('name', 'Distances 2')
61+
trisurf(Mesh2, distances2,'linestyle', 'none');
62+
axis equal
63+
title('Distances 2')
64+
colorbar
65+

STL_Import.m

+264
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
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

Comments
 (0)