Source code for ddg.visualization.blender.bmesh

import bmesh
import ddg.math.euclidean
import ddg.math.projective as putils
from ddg.datastructures.halfedge.surface_generator import icosphere, cylinder
from ddg.conversion.blender.halfedge import hes_to_bmesh

import numpy as np
import math


###############         Generate bmesh functions       #######################
#############################################################################


[docs]def from_pydata(verts, edges, faces, bm=None, doubles=False): """ Parameters ---------- verts : list(coordinate vector) edges : list(tuples) faces : list(tuples) bm : bmesh (optional, default=None) doubles : bool (optional, default=False) Returns ------- bmesh """ if bm is None: bm = bmesh.new() else: bm.clear() for v in verts: bm.verts.new(v) bm.verts.ensure_lookup_table() if not doubles: for e in edges: e = [bm.verts[i] for i in e] bm.edges.new(e) for f in faces: f = [bm.verts[i] for i in f] bm.faces.new(f) else: found = set() for e in edges: temp = list(e) temp.sort() temp = tuple(temp) if not temp in found: e = [bm.verts[i] for i in e] bm.edges.new(e) found.add(temp) found = set() for f in faces: temp = list(f) temp.sort() temp = tuple(temp) if not temp in found: f = [bm.verts[i] for i in f] bm.faces.new(f) found.add(temp) return bm
############### Modify bmesh functions ####################### #############################################################################
[docs]def transform(bm, M): """ Transforms vertices of bmesh with given 3x3 or 4x4 matrix Parameters ---------- bm : bmesh bmesh to transform M : ndarray 3x3 or 4x4 transformation Martix """ if M.shape == (3, 3): for vert in bm.verts: vert.co = np.dot(M, np.array(vert.co)) elif M.shape == (4, 4): for vert in bm.verts: vert.co = putils.dehomogenize(np.dot(M, putils.homogenize(np.array(vert.co)))) else: raise ValueError("Shape of matrix must be (3,3) or (4,4).") return bm
[docs]def join(*bmeshes, free=False, bm=None): """Join bmeshes. Parameters ---------- *bmeshes : bmesh bmeshes to join. free : bool (optional, default=False) free joined bmeshes bm : bmesh (optional, default=None) bmesh to store joined bmeshes in Returns ------- bmesh bmesh 'containing' all given bmeshes. """ if bm is None: combined = bmesh.new() else: combined = bm combined.clear() for mesh in bmeshes: mesh.verts.ensure_lookup_table() mesh.verts.index_update() offset = len(combined.verts) for vert in mesh.verts: combined.verts.new(vert.co) combined.verts.index_update() combined.verts.ensure_lookup_table() for edge in mesh.edges: seq = tuple(combined.verts[i.index+offset] for i in edge.verts) combined.edges.new(seq) combined.edges.index_update() for face in mesh.faces: seq = tuple(combined.verts[i.index+offset] for i in face.verts) combined.faces.new(seq) combined.faces.index_update() if free: mesh.free() return combined
[docs]def bisect_plane(bm, normal=np.array((0, 0, 1)), dist=0): a = np.multiply(dist / np.linalg.norm(normal) ** 2, normal) result = bmesh.ops.bisect_plane(bm, dist=0., geom=bm.verts[:] + bm.edges[:] + bm.faces[:], plane_co=a, plane_no=normal, clear_inner=False, clear_outer=True)
[docs]def cut_between_coordinate_planes(bm, axis=0, dist=1., location=np.array((0, 0, 0))): normal = np.zeros(3) normal[axis] = 1 bisect_plane(bm, normal=normal, dist=dist + np.inner(location, normal)) bisect_plane(bm, normal=-normal, dist=dist - np.inner(location, normal))
[docs]def cut_bounding_box(bm, distances=np.array((1., 1., 1.)), location=np.array((0, 0, 0))): for i, dist in enumerate(distances): if dist is not None: cut_between_coordinate_planes(bm, axis=i, dist=dist, location=location)