12

With Object > Transform > Origin to Geometry, an object's origin is moved to its geometry's center. How can I get this center in script? I don't want to move its origin, I just need to get its center.

2 Answers2

14

Here's a low level way to calculate the bounding box center of an object:

import bpy

o = bpy.context.object
vcos = [ o.matrix_world * v.co for v in o.data.vertices ]
findCenter = lambda l: ( max(l) + min(l) ) / 2

x,y,z  = [ [ v[i] for v in vcos ] for i in range(3) ]
center = [ findCenter(axis) for axis in [x,y,z] ]

print( center )

EDITED:

@batFINGER proposed a much shorter and more efficient way to calculate the bounding box center (thanks!). Multiplication by the object's world matrix gives a global coordinate:

import bpy
from mathutils import Vector
o = bpy.context.object
local_bbox_center = 0.125 * sum((Vector(b) for b in o.bound_box), Vector())
global_bbox_center = o.matrix_world * local_bbox_center

It will find the center of the active object. The bounding box center (or "range" center) is calculated as the center between the minimum and maximum value in each axis.

It does not give you the same result that origin to geometry or origin to center of mass gives, but it is the center.

enter image description here

batFINGER
  • 84,216
  • 10
  • 108
  • 233
TLousky
  • 16,043
  • 1
  • 40
  • 72
  • I don't get it : if an object is set "origin to geometry" and if the object location is (0, 0, 0), this calculation will return (0, 0, 0) ? – lemon Aug 31 '16 at 12:12
  • Origin to geometry doesn't move the origin to the absolute center, for that you have the origin to center of mass option. – TLousky Aug 31 '16 at 12:19
  • Yes... but I think I have a example where this calculation (the answer) is not giving the same result as "origin to geometry" : typical example, a cone – lemon Aug 31 '16 at 12:21
  • http://pasteall.org/pic/show.php?id=106300 The calculation above find the bounding box center of the object. I.E. If you had a box at the same dimensions of the object, what its center would be.

    This is not the same calculation that blender performs when placing the origin to geometry, as you can see in the attached image.

    – TLousky Aug 31 '16 at 12:50
  • ok... thanks @TLousky... what I meant : this not seems to be an answer to the question – lemon Aug 31 '16 at 12:53
  • It is if you want to find the center (as the title implies), it's not if you want to get the exact same result that origin to geometry gives :) – TLousky Aug 31 '16 at 12:55
  • 1
    is this the same as bbox_centre = 1 / 8 * sum((Vector(b) for b in ob.bound_box), Vector()) – batFINGER Aug 31 '16 at 13:03
  • That's an awesome shortcut, @batFINGER, thanks! – TLousky Aug 31 '16 at 13:29
  • 2
    Can do the matrix mult once ob.matrix_world * (1 / 8 * sum((Vector(b) for b in ob.bound_box), Vector())) ie matrix_world * local_centre Which gives you the global coord of the centre of bounding box. The local centre is what you would subtract from each vert.co to change the origin to bbox centre. – batFINGER Aug 31 '16 at 14:39
  • 5
    TypeError: Element-wise multiplication: not supported between 'Matrix' and 'Vector' types so global_bbox_center = o.matrix_world @ local_bbox_center replace Star multiply with AT @ matrix multiply. – Master James Oct 11 '21 at 02:26
  • @MasterJames apologies for the stupid question but how does this script work? Is it suppose to output information? The script runs but nothing happens. No center info output, nothing in the console, origin doesnt change, no bounding box is created as in the picture above. – JeeperCreeper Oct 28 '21 at 02:57
  • @JeeperCreeper I noted an error that came up for me I guess here in the future (some update). The Star * for multiply doesn't work so the syntax for the right command is an @ instead (for matrix multiple). In the first part he uses the 'print' command and so you can see what happened (to any value in the console output) but you would simply use the value and assign it to some Empty or what-have-you. (If you're testing manually in the script pane you can just type the value name and it will print it there. – Master James Oct 29 '21 at 21:53
7

You can set the cursor to the object position, then set the origin to geometry, take this position and set back the origin to the cursor.

cursorLoc = bpy.context.scene.cursor_location.copy()
bpy.context.scene.cursor_location = obj.location
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
loc = obj.location.copy()
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
bpy.context.scene.cursor_location = cursorLoc

Here loc contains the geometry center position.

Edit : following some tests, it seems that 'origin to geometry center' is the average value of the vertices coordinates, so:

x, y, z = [ sum( [v.co[i] for v in obj.data.vertices] ) for i in range(3)]

count = float(len(obj.data.vertices))

center = obj.matrix_world * (Vector( (x, y, z ) ) / count )

For Blender 3.2 (use ops):

import bpy

def get_objcenter(obj): # save cursor location cursorLoc = bpy.context.scene.cursor.location.copy() #To undo this later, the cursor must be aligned with the location of the object. bpy.context.scene.cursor.location = obj.location # Align the object's origin with the object's center. bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY') # Master the center vector loc = obj.location.copy() # Align the object's origin with the object's location for later undo bpy.ops.object.origin_set(type='ORIGIN_CURSOR') # Undo the cursor location bpy.context.scene.cursor.location = cursorLoc

return loc

test

obj= bpy.context.object print(get_objcenter(obj))

For Blender 3.2 (use mathutils):

import bpy
from mathutils import Vector

def get_objcenter(obj): # Total value of each vertex x, y, z = [ sum( [v.co[i] for v in obj.data.vertices] ) for i in range(3)] # number of vertices count = float(len(obj.data.vertices)) # Divide the sum of each vector by the number of vertices # And make the position a world reference. center = obj.matrix_world @ (Vector( (x, y, z ) ) / count )

return center

test

obj = bpy.context.object print(get_objcenter(obj))

quellenform
  • 35,177
  • 10
  • 50
  • 133
lemon
  • 60,295
  • 3
  • 66
  • 136
  • That's what I think of at first but it's more of a work around. Thanks anyway. –  Aug 31 '16 at 11:22
  • @animel, yes... did not found any accurate definition of the center calculation – lemon Aug 31 '16 at 11:28
  • 7
    lemon you can (1.0 / count) * sum([v.co for v in verts], Vector()) – batFINGER Aug 31 '16 at 12:46
  • @batFINGER, definitively Python is a different way of thinking than other languages I know : ). Thanks ! – lemon Aug 31 '16 at 12:51
  • No idea why average coordinate is the center of the object but it's seems to be the way that Blender does it with "Origin to Geometry". Previously tried to use bounding box method but results didn't match with "Origin to Geometry" – FamousSnake May 21 '23 at 12:17
  • @FamousSnake, have a look here in complement. – lemon May 21 '23 at 18:06