# Object vertices coordinates are returned as an empty list occasionally

I am trying to get the furthest/closest vertices on both the X and Y axis for a mesh object. However, Blender returns empty lists for the coordinates for the same object. I initially thought the mesh has not been loaded into blender but then I realized that although the object has been loaded, I still might get an empty list. I may note that the problem occurs for random meshes and not only for an specific mesh. Below I post the relevant codes:

Here's how I load a mesh:

    obj_file = os.path.join(model_path)
bpy.ops.import_scene.obj(filepath=obj_file)

###############################################################
## obj file comes as a bunch of different meshes, unify them ##
###############################################################

obs = []
for ob in bpy.context.scene.objects:
# whatever objects you want to join...
if ob.type == 'MESH':
obs.append(ob)

if len(obs) > 1:
# Join the meshes
ctx = bpy.context.copy()
ctx['active_object'] = obs[0]
ctx['selected_objects'] = obs
# we need the scene bases as well for joining
ctx['selected_editable_bases'] = [bpy.context.scene.object_bases[ob.name] for ob in obs]
bpy.ops.object.join(ctx)

for ob in bpy.context.selectable_objects:
#if ob.name.startswith('simplified_model'):
if ob.type == 'MESH':
obj = ob            # this is for scoping reasons
obj.select = True
bpy.context.scene.objects.active = obj

if dissolve != None:
if dissolve:
# This is to be used for simplifying mesh models
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.dissolve_limited()
bpy.ops.object.mode_set(mode='OBJECT')

obj.collision.use = True


And then setting up the scene:

        bpy.context.scene.render.resolution_x = 448
bpy.context.scene.render.resolution_y = 448
bpy.context.scene.render.resolution_percentage = 100

s = 1.25
bpy.context.scene.camera.location.x = s
bpy.context.scene.camera.location.y = s
bpy.context.scene.camera.location.z = s

empty = bpy.data.objects.new('empty', None)
bpy.context.scene.update()

camera_follow_constraint = bpy.context.scene.camera.constraints.new(type='TRACK_TO')
camera_follow_constraint.target = obj #empty
camera_follow_constraint.track_axis = 'TRACK_NEGATIVE_Z'
camera_follow_constraint.up_axis = 'UP_Y'


And finally here's how I get the coordinates. Sometimes, the xs or ys lists are returned empty and I haven't been able to find out why:

mat = obj.matrix_world
coords = [mat * vert.co for vert in obj.data.vertices]

xs = [co.x for co in coords]
ys = [co.y for co in coords]


I am using Python 3. I would appreciate if someone can give me some help on this.

Here are two links for two meshes for which I experienced the problem. I may note again that the problem does not only occur for these two models. I have thousands of meshes and each time it occurs for a bunch of them:

Thanks

• Can you provide a minimal code example to reproduce your problem? Basically you mean that obj contains no data. It is not clear from your code what obj actually is. It looks like it is the last of bpy.context.selectable_objects: of type mesh. Are you sure this object exists and actually have vertices? Print out some information about this object. – Noidea Oct 7 '16 at 15:24
• Well the thing is the problem occurs occasionally. Sometimes it occurs for the same mesh and sometimes it does not. I update my original post and put some links to some of the mesh models I use. I select the last (and actually first) mesh since I only have one mesh object in the scene (in addition to camera and lamp/light). – Amir Oct 7 '16 at 15:43
• well, add print obj.name to check that you have the correct object – Noidea Oct 7 '16 at 15:51

Here is a take on this. Removed the context override on the join op, the import wavefront obj operator returns all imported objects as selected. This is the list context.selected_objects whereas scene.objects is all the objects in the scene. Not sure why you would want to use context.selectable_objects for this case.

Simply deselect if not a mesh, assign first mesh obj as active (if there are mesh objs) , and then call bpy.ops.object.join().

Used bmesh for limited dissolve, takes away the need to pop modes.

Tested fine on object1.obj

import bpy
from bpy import context
scene = context.scene
import bmesh

# make a bmesh
bm = bmesh.new()
dissolve = True

bpy.ops.import_scene.obj(filepath=filepath)

mesh_objs = []
for o in context.selected_objects:
if not o.type == 'MESH':
o.select = False
print(o.name, "not a mesh")
continue
if dissolve:
# use bmesh to dissolve
bm.from_mesh(o.data)
print("Pre dissolve", len(bm.verts))
geom = bmesh.ops.dissolve_limit(bm, angle_limit=0.082665,
verts=bm.verts,
edges=bm.edges,
delimit=0)
bm.to_mesh(o.data)
print("Post dissolve", len(o.data.vertices))
bm.clear()
# append the mesh object
mesh_objs.append(o)
bm.free()
# if no mesh objs do nothing
if mesh_objs:
scene.objects.active = mesh_objs[0]

bpy.ops.object.join()
# newly joined obj
obj = scene.objects.active
# look at verts
verts = obj.data.vertices
vertsx = [v.co.x for v in verts]
vertsy = [v.co.y for v in verts]
print(len(vertsx), len(vertsy))

• A list comprehension like meshes = [o for o in bpy.context.selected_objects[:] if o.type=="MESH"] might be suitable in this case. – p2or Oct 8 '16 at 16:23
• @poor would still need to go thru list to deselect non meshes for the join operator. Thought it was easier to deselect or dissolve and append in the loop in this case. – batFINGER Oct 8 '16 at 16:35
• yeah, you are right. The loop is required, only thought we can save some lines... – p2or Oct 8 '16 at 16:48