Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
bl_info = {
"name": "Genus",
"description": "Compute genus",
"author": "TheBusyTypist",
"category": "Object"
}
import bpy
import bmesh
import math
def AngleDefects(bm):
d = 0.0
for v in bm.verts:
k = 0.0
# Traverse all adjacent edges
for i, _ in enumerate(v.link_edges):
u = v.link_edges[i]
w = v.link_edges[i - 1]
du = (u.other_vert(v).co - v.co).normalized()
dw = (w.other_vert(v).co - v.co).normalized()
c = du * dw
# Saturate
c = max(-1, min(1, c))
k += math.acos(c)
d += (2 * math.pi - k)
return d
def AngleDefects2(bm):
d = 0.0
for v in bm.verts:
k = 0.0
# Traverse all adjacent faces
for f in v.link_faces:
# Filter the adjacent edges
edges = []
for e in v.link_edges:
if e in f.edges:
edges.append(e)
assert len(edges) == 2
du = (edges[0].other_vert(v).co - v.co).normalized()
dw = (edges[1].other_vert(v).co - v.co).normalized()
c = du * dw
# Saturate
c = max(-1, min(1, c))
k += math.acos(c)
d += (2 * math.pi - k)
return d
class ComputeGenus(bpy.types.Operator):
"""Compute genus"""
bl_idname = "object.compute_genus"
bl_label = "Compute genus"
bl_options = {"REGISTER"}
def execute(self, context):
m = context.object.data
bm = bmesh.new()
bm.from_mesh(m)
d = AngleDefects2(bm)
genus = (2 - d / (2 * math.pi)) / 2
self.report({"INFO"},
"Angle defect: {d}; genus: {g}".format(d=d, g=genus))
return {"FINISHED"}
def register():
bpy.utils.register_class(ComputeGenus)
def unregister():
bpy.utils.unregister_class(ComputeGenus)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.