[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [1149] contrib/py/scripts/addons/ mesh_bridge.py: Version 1.4.0
Bart Crouch
bartius.crouch at gmail.com
Thu Nov 11 14:16:24 CET 2010
Revision: 1149
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-extensions&revision=1149
Author: crouch
Date: 2010-11-11 14:16:24 +0100 (Thu, 11 Nov 2010)
Log Message:
-----------
Version 1.4.0
Major restructuring of code is done.
Should be stable.
Modified Paths:
--------------
contrib/py/scripts/addons/mesh_bridge.py
Modified: contrib/py/scripts/addons/mesh_bridge.py
===================================================================
--- contrib/py/scripts/addons/mesh_bridge.py 2010-11-11 10:41:05 UTC (rev 1148)
+++ contrib/py/scripts/addons/mesh_bridge.py 2010-11-11 13:16:24 UTC (rev 1149)
@@ -16,9 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
-
"""
Bridge
@@ -26,23 +24,23 @@
- Select a mesh and go into editmode
- Select two or more edge-loops
- Press Ctrl+F
-- Select the Bridge option
+- Select the Bridge or Loft option
"""
bl_addon_info = {
'name': 'Bridge',
'author': 'Bartius Crouch',
- 'version': (1,1,0),
- 'blender': (2,5,4),
- 'api': 31878,
+ 'version': (1, 4, 0),
+ 'blender': (2, 5, 5),
+ 'api': 32738,
'location': 'View3D > Ctrl+F > Bridge',
- 'warning': '', # used for warning icon and text in addons panel
- 'description': 'Connect two or more loops of vertices.',
- 'wiki_url': 'http://wiki.blender.org/index.php/Extensions:Py/'\
- 'Scripts/',
- 'tracker_url': 'https://projects.blender.org/tracker/index.php?'\
- 'func=detail&aid=23889&group_id=153&atid=467',
+ 'warning': '',
+ 'description': 'Bridge two, or loft several, loops of vertices.',
+ 'wiki_url': 'http://wiki.blender.org/index.php/Extensions:2.5/Py/'\
+ 'Scripts/Modeling/Bridge',
+ 'tracker_url': 'http://projects.blender.org/tracker/index.php?'\
+ 'func=detail&aid=23889&group_id=153&atid=468',
'category': 'Mesh'}
@@ -51,14 +49,37 @@
# gather initial data
-def initialise():
+def initialise(interpolation):
global_undo = bpy.context.user_preferences.edit.use_global_undo
bpy.context.user_preferences.edit.use_global_undo = False
bpy.ops.object.mode_set(mode = 'OBJECT')
mesh = bpy.context.active_object.data
- return global_undo, mesh
+ old_selected_faces = [face.index for face in mesh.faces if face.select and not face.hide]
+
+ smooth = False
+ if mesh.faces:
+ if sum([face.use_smooth for face in mesh.faces])/len(mesh.faces) >= 0.5:
+ smooth = True
+ if interpolation == 'cubic':
+ # dictionary with the edge-key as key
+ # and a list of connected valid faces as value
+ face_blacklist = [face.index for face in mesh.faces if face.select or face.hide]
+ edge_faces = dict([[edge.key, []] for edge in mesh.edges if not edge.hide])
+ for face in mesh.faces:
+ if face.index in face_blacklist:
+ continue
+ for key in face.edge_keys:
+ edge_faces[key].append(face)
+ # dictionary with the edge-key as key and edge as value
+ edgekey_to_edge = dict([[edge.key, edge] for edge in mesh.edges if edge.select and not edge.hide])
+ else:
+ edge_faces = False
+ edgekey_to_edge = False
+
+ return global_undo, mesh, old_selected_faces, smooth, edge_faces, edgekey_to_edge
+
# clean up and set settings back to original state
def terminate(global_undo):
bpy.ops.object.mode_set(mode = 'EDIT')
@@ -67,7 +88,17 @@
# return a list of 2 non-connected loops (vertex indices), or False
def get_selection(mesh):
- selected_edges = [edge.key for edge in mesh.edges if edge.select and not edge.hide]
+ # create list of internal edges, which should be skipped
+ eks_of_selected_faces = [item for sublist in [face.edge_keys for face in mesh.faces if face.select and not face.hide] for item in sublist]
+ edge_count = {}
+ for ek in eks_of_selected_faces:
+ if ek in edge_count:
+ edge_count[ek] += 1
+ else:
+ edge_count[ek] = 1
+ internal_edges = [ek for ek in edge_count if edge_count[ek]>1]
+
+ selected_edges = [edge.key for edge in mesh.edges if edge.select and not edge.hide and edge.key not in internal_edges]
vert_connections = {}
loops = []
# dict with vertex index as key, list of connected vertices as value
@@ -79,12 +110,12 @@
if len(vert_connections[key[i]]) == 2:
return False
vert_connections[key[i]].append(key[1-i])
-
+
while len(vert_connections) > 0:
loop = [iter(vert_connections.keys()).__next__()]
growing = True
sides_left = True
-
+
while growing:
# no more connection data for current vertex
if loop[-1] not in vert_connections:
@@ -93,41 +124,31 @@
sides_left = False
else:
growing = False
- # test first possible connection
- elif vert_connections[loop[-1]][-1] not in loop:
- new_vert = vert_connections[loop[-1]].pop()
- if len(vert_connections[loop[-1]]) == 0:
- del vert_connections[loop[-1]]
- if new_vert in vert_connections:
- # remove connection both ways
- if loop[-1] in vert_connections[new_vert]:
- if len(vert_connections[new_vert]) == 1:
- del vert_connections[new_vert]
- else:
- vert_connections[new_vert].remove(loop[-1])
- loop.append(new_vert)
- # test second possible connection
- elif len(vert_connections[loop[-1]]) > 1:
- if vert_connections[loop[-1]][-2] not in loop:
- new_vert = vert_connections[loop[-1]].pop(-2)
- if len(vert_connections[loop[-1]]) == 0:
- del vert_connections[loop[-1]]
- if new_vert in vert_connections:
+ else:
+ extended = False
+ for connection_index, connecting_vertex in enumerate(vert_connections[loop[-1]]):
+ if connecting_vertex not in loop:
+ vert_connections[loop[-1]].pop(connection_index)
+ if len(vert_connections[loop[-1]]) == 0:
+ del vert_connections[loop[-1]]
# remove connection both ways
- if loop[-1] in vert_connections[new_vert]:
- if len(vert_connections[new_vert]) == 1:
- del vert_connections[new_vert]
+ if connecting_vertex in vert_connections:
+ if len(vert_connections[connecting_vertex]) == 1:
+ del vert_connections[connecting_vertex]
else:
- vert_connections[new_vert].remove(loop[-1])
- loop.append(new_vert)
- # found one end of the loop, continue with next
- elif sides_left == True:
- loop.reverse()
- sides_left = False
- # found both ends of the loop, stop growing
- elif sides_left == False:
- growing = False
-
+ vert_connections[connecting_vertex].remove(loop[-1])
+ loop.append(connecting_vertex)
+ extended = True
+ break
+ if not extended:
+ # found one end of the loop, continue with next
+ if sides_left == True:
+ loop.reverse()
+ sides_left = False
+ # found both ends of the loop, stop growing
+ elif sides_left == False:
+ growing = False
+
# check for circular
if loop[0] in vert_connections:
if loop[-1] in vert_connections[loop[0]]:
@@ -138,6 +159,8 @@
vert_connections[loop[0]].remove(loop[-1])
if len(vert_connections[loop[-1]]) == 1:
del vert_connections[loop[-1]]
+ else:
+ vert_connections[loop[-1]].remove(loop[-1])
loop = [loop, True]
else:
# not circular
@@ -186,66 +209,188 @@
return loops
-# calculate faces (list of lists, vertex indices) that need to be added
-def calculate_faces(mesh, loops, mode, reverse):
- faces = []
+# match up loops in pairs, used for multi-input bridging
+def match_loops(mesh, loops):
+ # calculate average loop normals and centers
+ normals = []
+ centers = []
+ for vertices, circular in loops:
+ normal = mathutils.Vector([0, 0, 0])
+ center = mathutils.Vector([0, 0, 0])
+ for vertex in vertices:
+ normal += mesh.vertices[vertex].normal
+ center += mesh.vertices[vertex].co
+ normals.append(normal / len(vertices) / 10)
+ centers.append(center / len(vertices))
+
+ # possible matches if loop normals are faced towards the center of the other loop
+ matches = dict([[i, []] for i in range(len(loops))])
+ matches_amount = 0
+ for i in range(len(loops) + 1):
+ for j in range(i+1, len(loops)):
+ if (centers[i] - centers[j]).length > (centers[i] - (centers[j] + normals[j])).length and \
+ (centers[j] - centers[i]).length > (centers[j] - (centers[i] + normals[i])).length:
+ matches_amount += 1
+ matches[i].append([(centers[i] - centers[j]).length, i, j])
+ matches[j].append([(centers[i] - centers[j]).length, j, i])
+ # if no loops face each other, just make matches between all the loops
+ if matches_amount == 0:
+ for i in range(len(loops) + 1):
+ for j in range(i+1, len(loops)):
+ matches[i].append([(centers[i] - centers[j]).length, i, j])
+ matches[j].append([(centers[i] - centers[j]).length, j, i])
+ for key, value in matches.items():
+ value.sort()
+
+ # make matches based on distance between centers and number of vertices in loops
+ new_order = []
+ for loop_index in range(len(loops)):
+ if loop_index in new_order:
+ continue
+ loop_matches = matches[loop_index]
+ if not loop_matches:
+ continue
+ shortest_distance = loop_matches[0][0]
+ shortest_distance *= 1.1
+ loop_matches = [[abs(len(loops[loop_index][0])-len(loops[loop[2]][0])), loop[0], loop[1], loop[2]] for loop in loop_matches if loop[0] < shortest_distance]
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list