Generates normals with multiple three-point coordinates
Show older comments
Hi!,I wanted to generate multiple three-dimensional coordinate normals in matlab and output them in fixed format to generate stl files, but I kept making mistakes. I want to know why, and I hope you can help me.
Nodes = [0 0 0;
4 0 0;
4 4 0;
0 4 0
4 0 2;
0 0 2;
4 1 2;
0 1 2;
0 1 1;
4 1 1;
4 2 1;
4 2 2;
0 2 2;
0 2 1;
0 4 2;
4 4 2];
singletriangle = [5 10 7;
5 2 10;
10 2 3;
3 11 10;
3 16 11;
16 12 11;
6 8 9;
6 1 9;
9 1 4;
9 4 14;
14 4 15;
14 15 13];
% Find the point coordinates according to the triangle index
points_triangles = [Nodes(singletriangle,1),Nodes(singletriangle,2),Nodes(singletriangle,3)];
% Find the point coordinates of each column (three-dimensional)
points_one=points_triangles(1:length(points_triangles)/3,:);
points_two=points_triangles(length(points_triangles)/3+1:length(points_triangles)/3*2,:);
points_three=points_triangles(length(points_triangles)/3*2+1:length(points_triangles),:);
% Subtract the matrix and compute the vector
vectors_one=points_two-points_one;
vectors_two=points_three-points_one;
% Take the cross product of two vectors
normal_vectors=cross(vectors_one,vectors_two);
% Normalizes the 3D vector so that its modulus is equal to 1
normalized_normal_vectors=normal_vectors./norm(normal_vectors);
% Initializes the empty array
output=zeros(length(points_one)*4,3);
% Write output data
for i=1:length(points_one)
output(i*4-3,:)=normalized_normal_vectors(i,:);
output(i*4-2,:)=points_one(i,:);
output(i*4-1,:)=points_two(i,:);
output(i*4,:)=points_three(i,:);
end
% Output content
output=output';
STL_file_name=['lin123','.stl'] ;
STL_file = fopen (STL_file_name,'wt');
fprintf (STL_file,'solid %s\n','solid');
fprintf (STL_file, ' facet normal %14e %14e %14e\n outer loop\n vertex %14e %14e %14e\n vertex %14e %14e %14e\n vertex %14e %14e %14e\n endloop\n endfacet\n',output);
fprintf (STL_file,'endsolid %s\n','solid' );
fclose (STL_file);
2 Comments
DGM
on 27 Sep 2025
Unless you're just doing this as an exercise in making an STL encoder for sake of whimsy (been there), none of this is necessary. Just write the FV data to an STL. The normals are calculated internally by the encoder.
% the model
F = [5 10 7; 5 2 10; 10 2 3; 3 11 10; 3 16 11; 16 12 11; 6 8 9; 6 1 9; 9 1 4; 9 4 14; 14 4 15; 14 15 13];
V = [0 0 0; 4 0 0; 4 4 0; 0 4 0; 4 0 2; 0 0 2; 4 1 2; 0 1 2; 0 1 1; 4 1 1; 4 2 1; 4 2 2; 0 2 2; 0 2 1; 0 4 2; 4 4 2];
% write the file to a binary STL
T = triangulation(F,V);
stlwrite(T,'test.stl')
That will write a compact, portable binary STL. Unless you want to read the triangulation to your children as a bedtime story, send it via teletype, or are trying to create a file which is compatible with a pre-1987 version of the slicer used with the prototype of the SLA-1, ASCII STL is just a waste of space (and often a silent degradation in precision). Otherwise, if unquestionably desired or absolutely necessary, you can just do:
% okay fine, write an ASCII STL instead
% this will be written with enough precision
% to losslessly represent float32 coordinates and normals
stlwrite(T,'test.stl','text')
Otherwise, if you just need to get the unit normals for some other reason, you can get them from the triangulation object:
% just get the face normals
N = faceNormal(T); % bam done.
The STL encoder is available in R2018b+. The use of triangulation.faceNormal is available in R2013a+, and similar functionality is available via the TriRep class back to R2009a.
William Rose
on 29 Sep 2025
@DGM, thanks for the info and the humor!
Accepted Answer
More Answers (0)
Categories
Find more on STL (STereoLithography) in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!