@CoDEmanX,
if I understand well, the problem of slowness is not only in calling an object in C. But there when we reference a C object as a python object that is soon thrown into garbage.
I decided to do some tests making less reference to the object C and using list comprehensions:
print('-----------------------------------------------')
import bpy
import bmesh
import time
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
time_start = time.time()
list1 = []
for e in bm.edges:
v1, v2 = e.verts
list1.append((v1.co, v2.co))
print("Method1 Finished in %.4f sec" % (time.time() - time_start))
time_start = time.time()
list2 = [(v1.co, v2.co) for v1, v2 in [e.verts for e in bm.edges]]
print("Method2 Finished in %.4f sec" % (time.time() - time_start))
print(list1 == list2)
The result is promising with high Polly objects.
------------------------------
Method1 Finished in 0.6875 sec
Method2 Finished in 0.5653 sec
True
But the big difference is in the script execution shown before
def intersect_bound_box_edge_edge(a1, a2, b1, b2, precision = 0.0001):
bbx1 = sorted([a1[0], a2[0]])
bbx2 = sorted([b1[0], b2[0]])
if ((bbx1[0] - precision) <= bbx2[1]) and (bbx1[1] >= (bbx2[0] - precision)):
bby1 = sorted([a1[1], a2[1]])
bby2 = sorted([b1[1], b2[1]])
if ((bby1[0] - precision) <= bby2[1]) and (bby1[1] >= (bby2[0] - precision)):
bbz1 = sorted([a1[2], a2[2]])
bbz2 = sorted([b1[2], b2[2]])
if ((bbz1[0] - precision) <= bbz2[1]) and (bbz1[1] >= (bbz2[0] - precision)):
return True
else:
return False
else:
return False
else:
return False
def list_BVH1(edges1, edges2, precision = 0.0001):
tmp_set1 = set()
tmp_set2 = set()
for ed1 in edges1:
for ed2 in edges2:
if ed1 != ed2:
a1, a2 = ed1.verts
b1, b2 = ed2.verts
intersect = intersect_bound_box_edge_edge(a1.co, a2.co, b1.co, b2.co, precision = precision)
if intersect:
tmp_set1.add(ed1)
tmp_set2.add(ed2)
return tmp_set1, tmp_set2
def list_BVH2(edges1, edges2, precision = 0.0001):
aco = [(v1.co,v2.co) for v1,v2 in [e.verts for e in edges1]]
bco = [(v1.co,v2.co) for v1,v2 in [e.verts for e in edges2]]
tmp_set1 = set()
tmp_set2 = set()
for i1, ed1 in enumerate(aco):
for i2, ed2 in enumerate(bco):
if ed1 != ed2:
a1, a2 = ed1
b1, b2 = ed2
a1x, a2x = a1.x, a2.x
b1x, b2x = b1.x, b2.x
bbx1 = (a1x, a2x) if a1x < a2x else (a2x, a1x)
bbx2 = (b1x, b2x) if b1x < b2x else (b2x, b1x)
if ((bbx1[0] - precision) <= bbx2[1]) and (bbx1[1] >= (bbx2[0] - precision)):
a1y, a2y = a1.y, a2.y
b1y, b2y = b1.y, b2.y
bby1 = (a1y, a2y) if a1y < a2y else (a2y, a1y)
bby2 = (b1y, b2y) if b1y < b2y else (b2y, b1y)
if ((bby1[0] - precision) <= bby2[1]) and (bby1[1] >= (bby2[0] - precision)):
a1z, a2z = a1.z, a2.z
b1z, b2z = b1.z, b2.z
bbz1 = (a1z, a2z) if a1z < a2z else (a2z, a1z)
bbz2 = (b1z, b2z) if b1z < b2z else (b2z, b1z)
if ((bbz1[0] - precision) <= bbz2[1]) and (bbz1[1] >= (bbz2[0] - precision)):
tmp_set1.add(edges1[i1])
tmp_set2.add(edges2[i2])
return tmp_set1, tmp_set2
import bpy
import bmesh
import time
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
a = bm.edges
b = list(set([x for y in [v2.link_edges for v2 in [v for v in bm.faces.active.verts]] for x in y]))
print('--------------------------------')
time_start = time.time()
result1 = list_BVH1(a,b)
print("list_BVH1 Finished in %.2f sec" % (time.time() - time_start))
time_start = time.time()
result2 = list_BVH2(a,b)
print("list_BVH2 Finished in %.2f sec" % (time.time() - time_start))
print(result1 == result2)
This last script presented encouraging results :
--------------------------------
list_BVH1 Finished in 18.44 sec
list_BVH2 Finished in 5.76 sec
True
I believe I can further accelerate if I improve the list comprehensions. Maybe if I execute the whole function inside a list comprehensions the result could be instantaneous.