I’ve been programming c and php long enough to know that this code is not good. It’s works fine, but I feel like I could do it the python way in a couple lines. I pass in a list of vertices and I want to find the center point. Is there a bpy function for this, or a cleaner way.
import bpy
from mathutils import Vector
from functools import reduce
ob = bpy.context.object
me = ob.data
verts = me.vertices
center = reduce(Vector.__add__, (v.co for v in verts))
try:
bpy.context.scene.cursor_location = ob.matrix_world * (center / len(verts))
except ZeroDivisionError:
print("%s has no vertices!" % me.name)
A bit less fancy would be:
import bpy
from mathutils import Vector
ob = bpy.context.object
me = ob.data
verts = me.vertices
assert len(verts) != 0, "%s has no vertices!" % me.name
center = Vector()
for v in verts:
center += v.co
bpy.context.scene.cursor_location = ob.matrix_world * (center / len(verts))
And to stay as close as possible to your approach:
def get_center_point(self, verts):
vertcount = len(verts)
vertsum = [0, 0, 0]
for v in verts:
vertsum[0] += v.co[0]
vertsum[1] += v.co[1]
vertsum[2] += v.co[2]
if (vertcount > 0):
vertsum[0] /= vertcount
vertsum[1] /= vertcount
vertsum[2] /= vertcount
return vertsum
That’s awesome! Thank you. I changed the function signature to pass in the object and then re-used center to hold the center instead of printing it, and returned it. It looks so much nicer. I added a comment in the code thanking and crediting you. The comments don’t line up in the code tags
def getCenterPoint(self,verts,myobj):
center = reduce(Vector.__add__, (v.co for v in verts)) #Thanks to CoDEmanX
try: #For this great snippet
center = myobj.matrix_world * (center / len(verts))
except ZeroDivisionError:
print("%s has no vertices!" % myobj.me.name)
return center
Ahh, yes, thank you. Change made. It was a runtime error, and I never have a divide by zero condition.
Here’s my latest function, which works, but it makes me sad to look at. Any ideas on improvement? The last three lines should be accomplished in 1 line, something like:
total /= len(myverts)
def getVariance(self,myverts,myobj):
center = self.getCenterPoint(myverts,myobj)
print(center)
total = [0.0,0.0,0.0]
for v in myverts:
total[0] += pow((v.co.x - center[0]),2)
total[1] += pow((v.co.y - center[1]),2)
total[2] += pow((v.co.z - center[2]),2)
foo += 1
total[0] = math.sqrt(total[0]) / len(myverts)
total[1] = math.sqrt(total[1]) / len(myverts)
total[2] = math.sqrt(total[2]) / len(myverts)
return total[0];
Vector does not have a pow method, but since you seem to be interested into X variance only, it is simple to do:
import bpy
import math
from functools import reduce
from mathutils import Vector
def get_center_point(verts, ob):
if len(verts) < 1:
print("%s has no vertices, returning object origin" % ob.data.name)
return ob.matrix_world.translation
center = reduce(Vector.__add__, (v.co for v in verts))
return ob.matrix_world * (center / len(verts))
def get_variance(verts, ob):
center = get_center_point(verts, ob)
try:
return sum((v.co.x - center.x) ** 2 for v in verts) ** 0.5 / len(verts)
except ZeroDivisionError:
# suppress exception and let function return without value (=None)
pass
ob = bpy.context.object
verts = ob.data.vertices
center = get_center_point(verts, ob)
bpy.context.scene.cursor_location = center
print("Center:", center)
print("Variance (X):", get_variance(verts, ob))
That’s great. It helps me a lot to look at good code, and make changes to it. I appreciate your time, and will make a comment in this function as well crediting and thanking you. Thanks again CoDEmanX.