2016-08-17 43 views
2

我想實現Newell的方法來根據here中的以下僞代碼計算Python中的曲面法線向量。使用Newell的方法計算Python中的曲面法線

Begin Function CalculateSurfaceNormal (Input Polygon) Returns Vector 

    Set Vertex Normal to (0, 0, 0) 

    Begin Cycle for Index in [0, Polygon.vertexNumber) 

     Set Vertex Current to Polygon.verts[Index] 
     Set Vertex Next to Polygon.verts[(Index plus 1) mod Polygon.vertexNumber] 

     Set Normal.x to Sum of Normal.x and (multiply (Current.y minus Next.y) by (Current.z plus Next.z)) 
     Set Normal.y to Sum of Normal.y and (multiply (Current.z minus Next.z) by (Current.x plus Next.x)) 
     Set Normal.z to Sum of Normal.z and (multiply (Current.x minus Next.x) by (Current.y plus Next.y)) 

    End Cycle 

    Returning Normalize(Normal) 

End Function 

這裏是我的代碼:

Point3D = collections.namedtuple('Point3D', 'x y z') 

def surface_normal(poly): 
    n = [0.0, 0.0, 0.0] 

    for i, v_curr in enumerate(poly): 
     v_next = poly[(i+1) % len(poly)] 
     n[0] += (v_curr.y - v_next.y) * (v_curr.z - v_next.z) 
     n[1] += (v_curr.z - v_next.z) * (v_curr.x - v_next.x) 
     n[2] += (v_curr.x - v_next.x) * (v_curr.y - v_next.y) 

    normalised = [i/sum(n) for i in n] 

    return normalised 

def test_surface_normal(): 
    poly = [Point3D(0.0, 0.0, 0.0), 
      Point3D(0.0, 1.0, 0.0), 
      Point3D(1.0, 1.0, 0.0), 
      Point3D(1.0, 0.0, 0.0)] 

    assert surface_normal(poly) == [0.0, 0.0, 1.0] 

這未能在標準化步驟,因爲n在這一點上是[0.0, 0.0, 0.0]。如果我理解正確,應該是[0.0, 0.0, 1.0](Wolfram Alpha的confirmed)。

我在這裏做錯了什麼?有沒有更好的方法來計算python中的曲面法線?我的多邊形總是平面的,所以如果還有其他方法,Newell方法不是絕對必要的。

回答

0

好的,問題其實是一個愚蠢的問題。

線條喜歡:

n[0] += (v_curr.y - v_next.y) * (v_curr.z - v_next.z) 

應該是:

n[0] += (v_curr.y - v_next.y) * (v_curr.z + v_next.z) 

在第二組括號中的值應該被添加,而不是相減。

1

如果您需要Newell方法的替代方法,您可以使用2個非平行向量的交叉乘積。這應該適用於您提供的任何平面形狀。我知道該理論認爲它適用於凸多邊形,但我們在Wolfram Alpha上看到的例子爲偶凹多邊形返回適當的曲面法線(例如,bowtie多邊形)。

+0

是的,我得到零除 - 因爲我試圖規範'[0,0,0]'這是不是一個有效的向量。這不應該是代碼中當時的價值。平面上,我的意思是第一個。 3D空間中的2D多邊形。 –

+0

好吧,我也得到了這個(我通過使用這個來避免它 - 「normalised = [i/sum(n)if sum(n)!= 0.0 else 0 for i in n]' - 只能通過它) 。你的多邊形是否總是凸起的,還是有可能不是? – dblclik

+0

它們可以是任何形狀,但不能自相交。而你的解決方法可能會失敗,例如使用矢量'[-0.5,0.0,0.5]'。我正在使用'try:except:'塊,但如果算法運行正常,則不需要。 –