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)