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)