# Generates normals with multiple three-point coordinates

2 views (last 30 days)
Chenglin Li on 25 Feb 2023
Commented: William Rose on 25 Feb 2023
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);

William Rose on 25 Feb 2023
Edited: William Rose on 25 Feb 2023
[edit: I simplified the calculation of the normalized normal vectors]
I ran your code. It runs without error. It makes an STL file (attached). I can render the STL file at https://www.viewstl.com without getting an error. What is the problem?
The rendered object looks like two 2-D sheets, rather than a 3-D object. I don;t know what you expect your object to look like. I recommend that you start with a simple set of points. I re-ran your code with 4 points and 4 triangles, to make a tetrahedron. It works. The STL file produces a tetrahedron when viewed at https://www.viewstl.com.
Nodes = [0 0 0;
1 0 0;
0 1 0;
0 0 1];
singletriangle = [1 3 2;
1 2 4;
1 4 3;
2 3 4];
% 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=['tetra.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);
The code above makes a tetrahedron. Maybe you are not happy with the normal vectors. Let us inspect them:
disp(normal_vectors)
0 0 -1 0 -1 0 -1 0 0 1 1 1
These normal vectors point in the expected directions: outward from each face.
However, the normalized normal vectors do not have unit length:
disp(normalized_normal_vectors)
0 0 -0.5000 0 -0.5000 0 -0.5000 0 0 0.5000 0.5000 0.5000
That is a problem. Modify the normalization command. You did
normalized_normal_vectors=normal_vectors./norm(normal_vectors);
That does not give the desired result, because norm(X) returns a scalar when X is a matrix. Use vecnorm() instead:
nnv=normal_vectors./(vecnorm(normal_vectors'))';
disp(nnv)
0 0 -1.0000 0 -1.0000 0 -1.0000 0 0 0.5774 0.5774 0.5774
nnv looks like the correct set of normal vectors with unit length.
Good luck.

Chenglin Li on 25 Feb 2023
Thank you very much. I wanted to generate a concave surface before, but the figure was not what I wanted. After your program test, I found that it reached my expected effect, which helped me a lot, thank you！！！ William Rose on 25 Feb 2023
@Chenglin Li, you're welcome.