アストラルプリズム

PC、スマホ、ゲームなどの備忘録と日記

blender python 多角形の内角を知りたい

多角形の内角を知りたい。

bmeshを使う場合

f:id:katsumi3:20200120013355p:plain

一枚のポリゴンの場合
import bpy, bmesh
from math import degrees

obj = bpy.context.object
bpy.ops.object.mode_set(mode = 'EDIT')
bm = bmesh.from_edit_mesh(obj.data)
bm.faces.ensure_lookup_table()

rad = bm.faces[0].loops[0].calc_angle()
deg = degrees(rad)
print(deg)
bpy.ops.object.mode_set(mode = 'OBJECT')

結果
119.99998967892589

複数のポリゴンの場合

以下のようなものを考えてみたが隣り合う面が順番に並んでいるか確信が持てない。
メッシュをコピーして外側だけ取ってcalc_angle()した方が手っ取り早い気がする。
is_boundaryは境界かどうか調べてくれるコマンド。

import bpy, bmesh
from math import degrees

obj = bpy.context.object
bpy.ops.object.mode_set(mode = 'EDIT')
bm = bmesh.from_edit_mesh(obj.data)
bm.edges.ensure_lookup_table()
bou = []
for e in bm.edges:
        if e.is_boundary == True:
                bou.append(e)

for i , b in enumerate(bou):
       ang = bou[i-1].verts[1].link_loops[0].calc_angle() + bou[i].verts[0].link_loops[1].calc_angle()
       print(degrees(ang))


loopsは便利だけどループ選択順と頂点IDが一緒かどうかはまだ調べれてない。
loopsの詳しい解説は以下のサイトがめちゃめちゃ参考になった。
bm.faces[0].loops[0].link_loop_next.calc_angle()など、前後の値が取得できるのは超便利だと思う。
b3d.interplanety.org

複数のポリゴンの外側を選択する方法
全選択したのちに選択→ループ選択→境界選択
pythonの場合
bpy.ops.mesh.select_all(action = 'SELECT')
bpy.ops.mesh.region_to_loop()


ベクトルを使う方法

f:id:katsumi3:20200119232358p:plain

import bpy
from math import acos ,pi,degrees
from mathutils import Vector

p0 = Vector((0.866025,-0.5,0))
p1 = Vector((0.866025,0.5,0))
p2 = Vector((0,-1,0))

a = p0-p1
b = p0-p2

rad = acos(a.normalized().dot( b.normalized() ))
deg = degrees(rad)
print(deg)

結果
120.0000118302354

問題点
acosがー1から1の範囲外になるとmath domain errorになってしまう。
誤差から結構こういうの起きるので以下のように回避する。
三角関数はこういうの結構あってホント面倒orz

if a.normalized().dot( b.normalized() ) < -1:
    rad = 2 * pi
elif a.normalized().dot( b.normalized() ) > 1:
    rad = 0
else:
    rad = acos(a.normalized().dot( b.normalized() ))

print(deg)