[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [1065] contrib/py/scripts/addons/ mesh_bridge.py: Moved to contrib/py/scripts/addons/mesh_bridge.py

Brendon Murphy meta.androcto1 at gmail.com
Sun Sep 19 15:53:12 CEST 2010


Revision: 1065
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-extensions&revision=1065
Author:   meta-androcto
Date:     2010-09-19 15:53:12 +0200 (Sun, 19 Sep 2010)

Log Message:
-----------
Moved to contrib/py/scripts/addons/mesh_bridge.py
Thanks to Crouch.

Added Paths:
-----------
    contrib/py/scripts/addons/mesh_bridge.py

Added: contrib/py/scripts/addons/mesh_bridge.py
===================================================================
--- contrib/py/scripts/addons/mesh_bridge.py	                        (rev 0)
+++ contrib/py/scripts/addons/mesh_bridge.py	2010-09-19 13:53:12 UTC (rev 1065)
@@ -0,0 +1,418 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+
+"""
+Bridge
+
+How to use:
+- Select a mesh and go into editmode
+- Select two or more edge-loops
+- Press Ctrl+F
+- Select the Bridge option
+"""
+
+
+bl_addon_info = {
+    'name': 'Bridge',
+    'author': 'Bartius Crouch',
+    'version': (1,1,0),
+    'blender': (2,5,4),
+    'api': 31878,
+    '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',
+    'category': 'Mesh'}
+
+
+import bpy
+import mathutils
+
+
+# gather initial data
+def initialise():
+    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
+
+
+# clean up and set settings back to original state
+def terminate(global_undo):
+    bpy.ops.object.mode_set(mode = 'EDIT')
+    bpy.context.user_preferences.edit.use_global_undo = global_undo
+
+
+# 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]
+    vert_connections = {}
+    loops = []
+    # dict with vertex index as key, list of connected vertices as value
+    for key in selected_edges:
+        for i in range(2):
+            if key[i] not in vert_connections:
+                vert_connections[key[i]] = [key[1-i]]
+            else:
+                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:
+                if sides_left == True:
+                    loop.reverse()
+                    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:
+                        # 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)
+            # 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
+
+        # check for circular
+        if loop[0] in vert_connections:
+            if loop[-1] in vert_connections[loop[0]]:
+                # is circular
+                if len(vert_connections[loop[0]]) == 1:
+                    del vert_connections[loop[0]]
+                else:
+                    vert_connections[loop[0]].remove(loop[-1])
+                if len(vert_connections[loop[-1]]) == 1:
+                    del vert_connections[loop[-1]]
+                loop = [loop, True]
+            else:
+                # not circular
+                loop = [loop, False]
+        else:
+            # not circular
+            loop = [loop, False]
+        
+        loops.append(loop)
+    
+    if len(loops) < 2:
+        # can't bridge if there is only 1 loop (or none)
+        return False
+    else:
+        return loops
+
+
+# sort loops, so they are connected in the correct order when lofting
+def sort_loops(mesh, loops, loft_loop):
+    # simplify loops to single points, and prepare for pathfinding
+    x, y, z = [[sum([mesh.vertices[i].co[j] for i in loop[0]]) / len(loop[0]) for loop in loops] for j in range(3)]
+    nodes = [mathutils.Vector([x[i], y[i], z[i]]) for i in range(len(loops))]
+    
+    active_node = 0
+    open = [i for i in range(1, len(loops))]
+    path = [[0,0]]
+    # connect node to path, that is shortest to active_node
+    while len(open) > 0:
+        distances = [(nodes[active_node] - nodes[i]).length for i in open]
+        active_node = open[distances.index(min(distances))]
+        open.remove(active_node)
+        path.append([active_node, min(distances)])
+    # check if we didn't start in the middle of the path
+    for i in range(2, len(path)):
+        if (nodes[path[i][0]]-nodes[0]).length < path[i][1]:
+            temp = path[:i]
+            path.reverse()
+            path = path[:-i] + temp
+            break
+    
+    # reorder loops
+    loops = [loops[i[0]] for i in path]
+    # if requested, duplicate first loop at last position, so loft can loop
+    if loft_loop:
+        loops = loops + [loops[0]]
+    return loops
+
+
+# calculate faces (list of lists, vertex indices) that need to be added
+def calculate_faces(mesh, loops, mode, reverse):
+    faces = []
+    loop1, loop2 = [i[0] for i in loops]
+    loop1_circular, loop2_circular = [i[1] for i in loops]
+    circular = loop1_circular or loop2_circular
+    circle_full = False
+    
+    # if circular, rotate loops so they are aligned
+    if circular:
+        # make sure loop1 is the circular one (or both are circular)
+        if loop2_circular and not loop1_circular:
+            loop1_circular, loop2_circular = True, False
+            loop1, loop2 = loop2, loop1
+
+        # match start vertex of loop1 with loop2
+        distance_to_start1 = [(mathutils.Vector(mesh.vertices[loop1[i]].co) - mathutils.Vector(mesh.vertices[loop2[0]].co)).length for i in range(len(loop1))]
+        start1 = distance_to_start1.index(min(distance_to_start1))
+        loop1 = loop1[start1:] + loop1[:start1]
+        # if loop2 is also circular, check if loop2 also has to be shifted
+        if loop2_circular:
+            distance_to_start2 = [(mathutils.Vector(mesh.vertices[loop1[0]].co) - mathutils.Vector(mesh.vertices[loop2[i]].co)).length for i in range(len(loop2))]
+            start2 = distance_to_start2.index(min(distance_to_start2))
+            if min(distance_to_start2) < min(distance_to_start1):
+                loop2 = loop2[start2:] + loop2[:start2]
+        # make sure loop1 is the longest one
+        if len(loop2) > len(loop1):
+            loop1, loop2 = loop2, loop1
+            loop1_circular, loop2_circular = loop2_circular, loop1_circular
+        # have both loops face the same way
+        second_to_first, second_to_second, second_to_last = [(mathutils.Vector(mesh.vertices[loop1[1]].co) - mathutils.Vector(mesh.vertices[loop2[i]].co)).length for i in [0, 1, -1]]
+        last_to_first, last_to_second = [(mathutils.Vector(mesh.vertices[loop1[-1]].co) - mathutils.Vector(mesh.vertices[loop2[i]].co)).length for i in [0, 1]]
+        if (min(last_to_first, last_to_second) < min(second_to_first, second_to_second)) or \
+        (loop2_circular and second_to_last < min(second_to_first, second_to_second)):
+            if loop1_circular:
+                loop1.reverse()
+                loop1 = [loop1[-1]] + loop1[:-1]
+            else:
+                # set the circular loop to loop1 again
+                loop2.reverse()
+                loop2 = [loop2[-1]] + loop2[:-1]
+                loop1_circular, loop2_circular = True, False
+                loop1, loop2 = loop2, loop1
+    
+    # both loops have same length
+    if len(loop1) == len(loop2):
+        if not circular: # circular loops are already aligned correctly
+            # have both loops face the same way
+            length1 = sum([(mathutils.Vector(mesh.vertices[loop1[i]].co) - mathutils.Vector(mesh.vertices[loop2[i]].co)).length for i in range(len(loop1))])
+            loop1.reverse()

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list