I made a script that creates a circle, deselects all vertices in edit mode, selects first 5 vertices and then scales those vertices. I expected those vertices to be scaled with 3D cursor which sits in the middle of the circle, but instead the vertices are scaled with their median point.

I was experimenting with bpy.ops.transform.transform() function too, but to no avail.

import bpy

bpy.ops.mesh.primitive_circle_add(vertices=35, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
obj = bpy.context.active_object
obj.data.vertices[0].select = True
obj.data.vertices[1].select = True
obj.data.vertices[2].select = True
obj.data.vertices[3].select = True
obj.data.vertices[4].select = True
bpy.ops.transform.resize(value=(0.5, 0.5, 0.5),orient_type='CURSOR')

Script result:

enter image description here

Expected result:

enter image description here


3 Answers 3


Halve the coordinates.

Prob not an answer to question as asked, more so another approach without operators, mode switching or cursors.to produce the result.

Since the circle has origin at (0, 0, 0) then each verts coordinate is also the radial vector.

Simply halve vertex coordinate over the desired index range.

Test script.

import bpy

bpy.ops.mesh.primitive_circle_add(vertices=35, location=(0, 0, 0))
obj = bpy.context.active_object
me = obj.data
for i in range(5):
    me.vertices[i].co /= 2
  • $\begingroup$ Yeah that works. I have to pick up again school math. $\endgroup$
    – Dalibor-P
    Commented Jul 30, 2021 at 19:24

This is not a direct anser just typical knowledge from vector maths in game engines

usually you have to subtract origin from position so you localize the position vector then perform any transforms on the vectors and then re-add the origin


x = position - origin
x += scalar
x += origin

in your case the line bpy.ops.transform.resize(value=(0.5, 0.5, 0.5),orient_type='CURSOR')

the value 0.5 looks to be half the original position while 1.0 should show no visual change and 1.5 and so on should be greater

edit: no that 0.5 is in Blender units space not a scalar


This is a year later but I wanted to propose a solution I came across online to this problem. Other solutions here have proposed math calculations to "get around" this issue, but there is actually a solution. (Kinda)

Basically, from my understanding, regardless of what you set the pivot/orient_type to, in EDIT mode Blender will always perform that transformation as Median Point.

What you want to do is override the context, so that it performs the transformation over the cursor (or your specified pivot) instead of this default median point.

Source of where I first came across this solution

Credit to Garrett:

Overriding the context can be done like this:

def get_override(area_type, region_type):
    for area in bpy.context.screen.areas: 
        if area.type == area_type:             
            for region in area.regions:                 
                if region.type == region_type:                    
                    override = {'area': area, 'region': region} 
                    return override
    #error message if the area or region wasn't found
    raise RuntimeError("Wasn't able to find", region_type," in area ", area_type,
                        "\n Make sure it's open while executing script.")

#we need to override the context of our operator    
override = get_override( 'VIEW_3D', 'WINDOW' )
#rotate about the X-axis by 45 degrees
bpy.ops.transform.rotate(override, value=6.283/8, axis=(1,0,0)) 

Then, whatever your transformation is, pass in override as the first argument:

bpy.context.tool_settings.transform_pivot_point = "CURSOR" 
bpy.ops.transform.resize(override,value=(0.95, 0.95, 0.95))

Also, it should be noted that this means that when you run the script, it requires a visible 3D Viewer to be present.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .