Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab computing wrong surface normals?

I have a big FEM model from where I can get the "surface" of the model, say the elements and vertex that define the surface of that FEM model. For plotting purposes (nice plots are always a win!) I want to plot it nicely. My approach is just to use

lungs.Vertex=vtx;
lungs.Faces=fcs;
patch(lungs,'facecolor','r','edgecolor','none')

NOTE: I need edgecolor none, as this is 4D data and different FEM have different triangulation, if edges are plotted user will be dizzy.

enter image description here

However this will output everything in a really plain red color, which is not nice (as it can not show the complexity of the figure, which are lungs, for the attentive to details).

therefore I decided to use ligthing:

camlight; camlight(-80,-10); lighting phong; 

But again, this is not entirely correct. Actually it seems that the patch nromals are not computed correctly by Matlab.

enter image description here

My supposition is that maybe the patches are not always defined counter-clockwise and therefore some normals go to the wrong direction. However that is something its not straightforward to check.

Anyone has a similar problem, or ahint of how should I aproach this problem in order to have a nice surface ploted here?

EDIT

Just for the shake of plotting, here is the result obtained with @magnetometer answer:

enter image description here

like image 475
Ander Biguri Avatar asked Oct 20 '22 01:10

Ander Biguri


1 Answers

If your model gives you outward oriented normals, you can re-sort the faces of your model so that Matlab can properly calculate it's own normals. The following function works if you have triangular faces and outward oriented normals:

function [FaceCor,nnew]=SortFaces(Faces,Normals,Vertices)
FaceCor=Faces;
nnew=Normals*0;
for jj=1:size(Faces,1)
    v1=Vertices(Faces(jj,3),:)-Vertices(Faces(jj,2),:);
    v2=Vertices(Faces(jj,2),:)-Vertices(Faces(jj,1),:);

    nvek=cross(v2,v1); %calculate normal vectors
    nvek=nvek/norm(nvek); 
    nnew(jj,:)=nvek;
    if dot(nvek,Normals(jj,:))<0
        FaceCor(jj,:)=[Faces(jj,3) Faces(jj,2) Faces(jj,1)]; 
        nnew(jj,:)=-nvek;
    end

end

If your FEM model doesn't give you outward directed normals, one way could be to reconstruct the surface using e.g. a crust algorithm that gives you outward directed normals or correctly oriented patches.

EDIT: As you don't have normals, the only solution that comes to my mind is to reconstruct the surface. This implementation of the crust algorithm has worked well for me in the past. All you need to do is:

[FacesNew,NormalsNew]=MyRobustCrust(Vertices);

If I remember correctly, FacesNew are not yet oriented counterclockwise, but you can use the SortFaces algorithm I posted above to correct for this, as you now have correctly oriented face normals, i.e. run:

[FaceCor,~]=SortFaces(FacesNew,NormalsNew,Vertices)

If you use Matlab's reducepatch (e.g. reducedmodel=reducepatch(fullmodel,reduction); ) to reduce the number of vertices, you will have to reconstruct the surface again, as reducepatch doesn't seem to keep the correct orientation of the patches.

like image 100
magnetometer Avatar answered Oct 23 '22 02:10

magnetometer