Generates normals with multiple three-point coordinates

1 view (last 30 days)
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);

Accepted Answer

William Rose
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.

More Answers (1)

Chenglin Li
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!!!

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!