EnRound.py
Another version of makeRound.py.
Map vertices onto a sphere with the given centre in Edit mode.
The radius of sphere will be the average distance to the centre.
The default centre is 3d-cursor, otherwise average(i.e. gravity) of verts.
Please note that mapping will be unstable if a vert is too close to centre or axis.
import math import numpy as np import bmesh def getTotalLength(v, c): l = 0 for vv in v: l += math.sqrt(np.linalg.norm(v-c)) return l/len(v) # r=efficiency. isCrsrCntr=3d cursor as centre. # axis=along the axis if set. 0=x, 1=y, 2=z, None=no axis (point) def makeRound(r=1.0, isCrsrCntr=True, axis=None): if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='EDIT', toggle=False) o = bpy.context.scene.objects.active bm = bmesh.from_edit_mesh(o.data) # tX = tY = tZ = 0 v = [] for vts in bm.verts: if vts.select: v.append(vts.co) tX += vts.co[0] tY += vts.co[1] tZ += vts.co[2] # v = np.array(v) if len(v) == 0: print("No verts selected!") return if isCrsrCntr: c = bpy.context.scene.cursor_location else: # if cursor is not the center, avg(gravity) of verts is. c = np.array([tX/len(v), tY/len(v), tZ/len(v)]) # tl = 0 for vv in v: if axis is None: cc = c else: cc = np.array([0.0,0.0,0.0]) cc[axis] = vv[axis] cc[axis-1] = c[axis-1] cc[axis-2] = c[axis-2] tl += math.sqrt(np.linalg.norm(vv-cc)) avgLenth = tl/len(v) # for v in bm.verts: if v.select: if axis is None: cc = np.array(c) else: cc = np.array([0.0,0.0,0.0]) cc[axis] = v.co[axis] cc[axis-1] = c[axis-1] cc[axis-2] = c[axis-2] vt = np.array(v.co)-cc #print(c, v.co, vt, cc) s = np.linalg.norm(vt) if s > 0: v.co = (1-r)*np.array(v.co) + r*(cc + vt*avgLenth/s)