import bmesh
import bpy
import numpy as np
import ddg
import ddg.math.euclidean
from ddg.blender.mesh import duplicate_by_transformation_matrices, from_bmesh
[docs]def hes_to_bmesh(hes, co_attr="co", bpy_data=None):
"""
Converts a given half-edge surface into a bmesh.
The returned bmesh can then be used for handing over the surface to Blender.
Parameters
----------
hes : ddg.halfedge.Surface
The half-edge surface that shall be converted to a bmesh.
co_attr : coordinate attribute
The type of coordinates that will be taken for conversion.
bpy_data : bmesh (optional, default=None)
When given, bmesh to save the data into.
Returns
-------
bmesh
The bmesh corresponding to the input half-edge surface.
"""
if bpy_data is None:
hes_bmesh = bmesh.new()
else:
hes_bmesh = bpy_data
hes_bmesh.clear()
co = getattr(hes.verts, co_attr)
# create vertices
# by adding new vertices to the bmesh
for _ in range(len(hes.verts)):
hes_bmesh.verts.new()
# and handing over the coordinates
hes_bmesh.verts.ensure_lookup_table()
tmp_dict = dict() # for rebuilding the faces: save the correspondence of
# the bmesh-vertex and its corresponding hes-vertex-id
for i, v in enumerate(hes.verts):
hes_bmesh.verts[i].co = co[v]
tmp_dict[id(v)] = hes_bmesh.verts[i]
# create faces
for f in hes.faces:
face_verts = list(ddg.halfedge.face_vertices(f))
hes_bmesh.faces.new([tmp_dict[id(v)] for v in face_verts])
# catch edges not belonging to a face
for e in ddg.halfedge.single_edges(hes):
if e.face is None and e.opp.face is None:
hes_bmesh.edges.new([tmp_dict[id(e.opp.head)], tmp_dict[id(e.head)]])
return hes_bmesh
[docs]def face_objects(
heobj,
bobj,
collection=None,
location_attr="co",
rotation_attr=None,
scale_attr=None,
material_attr=None,
):
"""
places a Blender object at every face of the given half-edge object.
Parameters
----------
see vertex_object.
Returns
-------
vobjs: list
list of Blender objects placed at each face of given half-edge object.
Notes
-----
Half-edge face's does not natively store a location attribute this must be
calculated and added as an attribute before hand.
"""
faces = heobj.faces
transformations = []
material = []
for f in faces:
co_obj = np.array(list(getattr(f, location_attr)) + [1])
translation_mat = np.concatenate([np.eye(4, 3), co_obj.reshape(-1, 1)], axis=1)
if rotation_attr is not None:
rot_obj = getattr(f, rotation_attr)
scale_obj = getattr(f, scale_attr)
translation_mat = translation_mat @ rot_obj @ scale_obj
transformations.append(translation_mat)
if material_attr is not None:
material.append(getattr(f, material_attr))
if len(material) == 0:
material = None
vobjs = duplicate_by_transformation_matrices(
bobj, transformations, collection, material
)
return vobjs
[docs]def hes_to_mesh(hes, name="Halfedge mesh", co_attr="co"):
hes_bmesh = hes_to_bmesh(hes, co_attr=co_attr)
return from_bmesh(hes_bmesh, name, free=True)
[docs]def hes_to_blender_object(
hes, name="Halfedge object", co_attr="co", parent=None, matrix=np.eye(4)
):
hes_mesh = hes_to_mesh(hes, name=name, co_attr=co_attr)
obj = bpy.data.objects.new(name, hes_mesh)
obj.parent = parent
obj.matrix_local = matrix
bpy.context.scene.collection.objects.link(obj)
return obj