Matlab计算表面法线出现错误?

5

我有一个大型的FEM模型,可以从中获取模型的“表面”(即定义该FEM模型表面的元素和顶点)。为了画出美观的图形,我想把它漂亮地绘制出来。我的方法只是使用

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

注意:我需要边缘颜色无,因为这是4D数据,不同的FEM具有不同的三角化。如果绘制边缘,用户会感到头晕。
然而,这将输出一个非常平淡的红色,这样并不好(因为它不能展示图形的复杂性,这些是肺部,对于细节敏锐的人来说)。
因此,我决定使用光照:
camlight; camlight(-80,-10); lighting phong; 

但是实际上,这并不完全正确。实际上,Matlab似乎没有正确计算补丁法线。
我的假设是,也许补丁并不总是逆时针定义的,因此有些法线朝着错误的方向。但是这是一件不容易检查的事情。
是否有人遇到过类似的问题,或者在如何解决这个问题以便在此处画出漂亮的表面图方面有什么提示?
编辑:为了绘图,请看@magnetometer答案得到的结果:
1个回答

3
如果您的模型提供了外向法线,您可以重新排序模型的面,以便Matlab能够正确计算自己的法线。如果您有三角形面和外向法线,则以下函数有效:
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

如果你的有限元模型没有提供外向法线,一种方法是使用例如壳算法重构表面,以获得外向法线或正确定向的补丁。
编辑: 由于你没有法线,我想到的唯一解决方案就是重构表面。过去我曾使用壳算法的这个实现,效果很好。你需要做的就是:
[FacesNew,NormalsNew]=MyRobustCrust(Vertices);

如果我没记错的话,FacesNew 还没有逆时针定向,但是你可以使用我上面发布的 SortFaces 算法来进行纠正,因为现在你已经有了正确定向的面法线,即运行:
[FaceCor,~]=SortFaces(FacesNew,NormalsNew,Vertices)

如果你使用Matlab的reducepatch(例如reducedmodel=reducepatch(fullmodel,reduction);)来减少顶点数量,那么你将不得不重新构建表面,因为reducepatch似乎没有保持正确的贴片方向。

我肯定没有法线,这就是问题所在。如果所有的法线都是“向外定向”或“向内定向”,那么就不会有任何问题了,只需要重新定向它们就可以了。但从图片上看,似乎有些向内,有些向外,导致光照错误。 - Ander Biguri
非常有趣的函数。然而,我仍然遇到问题。我有“面法线”,但似乎Matlab需要“顶点法线”来设置光照。你建议我如何解决这个问题?Vertexnormals=mean(facenormals_with_that_vertex)? - Ander Biguri
我按照那样做了,得到了惊人的结果。非常感谢,这是一个非常好的答案。 - Ander Biguri
1
平均面法线可能是一种选择。根据您使用的Matlab版本,可能会有其他可能性。至少Matlab 2014似乎具有内置函数可以帮助:TR = triangulation(T,P);VN = vertexNormal(TR)值得一看,但我现在无法测试它们。 - magnetometer
我仍在使用2013b版本,但是平均值计算已经解决了我的问题,你可以在我提问的编辑中看到。虽然不是完美的,但足以让一两个主管印象深刻,所以它完成了工作!再次感谢;) - Ander Biguri
我认为如果你用 fliplr(Faces(jj,:)) 替换 [Faces(jj,3) Faces(jj,2) Faces(jj,1)],它就可以处理非三角形面了。 - saastn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接