Skip to main content
4 of 4
replaced http://blender.stackexchange.com/ with https://blender.stackexchange.com/

The LoopTools add-on proposed by TLousky, is obviously massively convenient and exactly what you want.


Given the above statement, the rest of this answer might be slightly academic, but can still be useful if you are interested in how something like this is scripted. My solution works on the assumption that:

  • the hole is a circle, and its vertices are the only things selected.
  • the object has all transforms applied
  • find the average coordinate (center of circle)
  • let it find the diameter by checking the distance between the average coordinate and any of the vertices.
  • use the average vector as a pivot point to scale away from.

code:

# This example assumes we have a mesh object in edit-mode

import bpy
import bmesh
from mathutils import Vector

def get_average_vector_of_selection(bm):
    avg_vector = Vector()
    num_vecs = 0
    for v in bm.verts:
        if v.select:
            num_vecs += 1
            avg_vector += v.co
    return (avg_vector / num_vecs)

def get_radius(bm, average):
    for v in bm.verts:
        if v.select:
            return (average-v.co).length

def scale_circle_verts(bm, new_radius):
    average = get_average_vector_of_selection(bm)
    # bpy.context.scene.cursor_location = average
    current_radius = get_radius(bm, average)
    print(current_radius)

    if new_radius == current_radius:
        return

    amount_to_rescale = current_radius / new_radius
    for v in bm.verts:
        if v.select:
            new_vec = (average).lerp(v.co, 1/amount_to_rescale)
            v.co = new_vec


obj = bpy.context.edit_object
me = obj.data
bm = bmesh.from_edit_mesh(me)

scale_circle_verts(bm, new_radius=0.2)

bmesh.update_edit_mesh(me, True)
zeffii
  • 39.9k
  • 9
  • 106
  • 189