6
$\begingroup$

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.

$\endgroup$
5
$\begingroup$

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

|improve this answer|||||
$\endgroup$
  • $\begingroup$ 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) ? $\endgroup$ – lemon Aug 31 '16 at 12:12
  • $\begingroup$ Origin to geometry doesn't move the origin to the absolute center, for that you have the origin to center of mass option. $\endgroup$ – TLousky Aug 31 '16 at 12:19
  • $\begingroup$ 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 $\endgroup$ – lemon Aug 31 '16 at 12:21
  • 1
    $\begingroup$ is this the same as bbox_centre = 1 / 8 * sum((Vector(b) for b in ob.bound_box), Vector()) $\endgroup$ – batFINGER Aug 31 '16 at 13:03
  • 2
    $\begingroup$ 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. $\endgroup$ – batFINGER Aug 31 '16 at 14:39
3
$\begingroup$

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
bpy.context.scene.cursor_location = obj.location
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
loc = obj.location
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 )
|improve this answer|||||
$\endgroup$
  • $\begingroup$ That's what I think of at first but it's more of a work around. Thanks anyway. $\endgroup$ – tea Aug 31 '16 at 11:22
  • $\begingroup$ @animel, yes... did not found any accurate definition of the center calculation $\endgroup$ – lemon Aug 31 '16 at 11:28
  • 5
    $\begingroup$ lemon you can (1.0 / count) * sum([v.co for v in verts], Vector()) $\endgroup$ – batFINGER Aug 31 '16 at 12:46
  • $\begingroup$ @batFINGER, definitively Python is a different way of thinking than other languages I know : ). Thanks ! $\endgroup$ – lemon Aug 31 '16 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.