Skip to main content
replaced http://blender.stackexchange.com/ with https://blender.stackexchange.com/
Source Link

The LoopTools add-on proposed by TLouskyLoopTools 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)

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)

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)
added 74 characters in body
Source Link
zeffii
  • 39.9k
  • 9
  • 106
  • 189

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


IfGiven 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 this might give some insight. 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)

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


If you are interested in how something like this is scripted this might give some insight. 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)

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)
added 5 characters in body
Source Link
zeffii
  • 39.9k
  • 9
  • 106
  • 189

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


If you are interested in how something like this is scripted this might give some insight.

I would propose a scripted My solution. works on the assumption that:

  • works on the assumption that:
    • the hole is a circle, and its vertices are the only things selected.
    • the object has all transforms applied
    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)

The LoopTools add-on proposed by TLousky, is obviously massively convenient. If you are interested in how something like this is scripted this might give some insight.

I would propose a scripted 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)

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


If you are interested in how something like this is scripted this might give some insight. 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)
Source Link
zeffii
  • 39.9k
  • 9
  • 106
  • 189
Loading