私は、hereの次の擬似コードに基づいて、Pythonの表面法線ベクトルを計算するためのNewellのメソッドを実装しようとしています。その時点でn
が[0.0, 0.0, 0.0]
あるので、Newellのメソッドを使用してPythonの表面法線を計算する
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]
これは、正規化ステップで失敗:
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
は、ここに私のコードです。正しく理解している場合は、[0.0, 0.0, 1.0]
(Wolfram Alphaのconfirmed)にする必要があります。
私はここで間違っていますか?そして、Pythonで表面法線を計算する良い方法はありますか?私のポリゴンは常に平面であるため、別の方法がある場合は、Newellのメソッドは絶対に必要なわけではありません。
はい、有効なベクトルではない '[0,0,0]'を正規化しようとしているので、ゼロで割ります。それはコードのその時点の値であってはなりません。そして、平面で、私は最初のものを意味します。 3D空間内の2Dポリゴン。 –
さて、私もそれを持っていました(これを使って避けました - 'normalised = [i/sum(n)ならsum(n)!= 0.0 else in 0 for i]' - 。あなたのポリゴンは常に凸であるか、そうでないポリゴンを持つことは可能でしょうか? – dblclik
これらは、自己交差していなくても、どのような形状であってもかまいません。そして、あなたの回避策は失敗します。たとえば、 '[-0.5、0.0、0.5] 'というベクトルで失敗するかもしれません。 'try:except:'ブロックを使っていましたが、アルゴリズムが正しく動作していれば必要ではありません。 –