[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [1733] contrib/py/scripts/addons/ mesh_looptools.py: LoopTools version 3.1.0

Bart Crouch bartius.crouch at gmail.com
Fri Mar 25 21:54:13 CET 2011


Revision: 1733
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=1733
Author:   crouch
Date:     2011-03-25 20:54:13 +0000 (Fri, 25 Mar 2011)
Log Message:
-----------
LoopTools version 3.1.0

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

Added: contrib/py/scripts/addons/mesh_looptools.py
===================================================================
--- contrib/py/scripts/addons/mesh_looptools.py	                        (rev 0)
+++ contrib/py/scripts/addons/mesh_looptools.py	2011-03-25 20:54:13 UTC (rev 1733)
@@ -0,0 +1,3750 @@
+# ##### 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>
+
+bl_info = {
+    'name': "LoopTools",
+    'author': "Bart Crouch",
+    'version': (3, 1, 0),
+    'blender': (2, 5, 7),
+    'api': 35672,
+    'location': "View3D > Toolbar and View3D > Specials (W-key)",
+    'warning': "",
+    'description': "Mesh modelling toolkit. Several tools to aid modelling",
+    'wiki_url': "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
+        "Scripts/Modeling/LoopTools",
+    'tracker_url': "http://projects.blender.org/tracker/index.php?"\
+        "func=detail&aid=26189",
+    'category': 'Mesh'}
+
+
+import bpy
+import mathutils
+import math
+
+
+##########################################
+####### General functions ################
+##########################################
+
+# check cache for stored information
+def cache_read(tool, object, mesh, input_method, boundaries):
+    # get cache
+    if "LoopTools_cache" not in object:
+        return(False, False, False, False, False)
+    cache = object["LoopTools_cache"]
+    # version check
+    try:
+        if cache["version"] != "".join(map(str, bl_info["version"])):
+            # cache written by other version of script
+            cache["version"] = "".join(map(str, bl_info["version"]))
+            return(False, False, False, False, False)
+    except:
+        # cache written by old script that didn't use version control
+        cache["version"] = "".join(map(str, bl_info["version"]))
+        return(False, False, False, False, False)
+    # current tool not cached yet
+    if tool not in cache:
+        return(False, False, False, False, False)
+    # check if input didn't change
+    if input_method != cache[tool]["input_method"]:
+        return(False, False, False, False, False)
+    if boundaries != cache[tool]["boundaries"]:
+        return(False, False, False, False, False)
+    cache_input = cache[tool]["input"]
+    input = ",".join([str(v.index) for v in mesh.vertices if \
+        v.select and not v.hide])
+    if input != cache_input:
+        return(False, False, False, False, False)
+    # reading values
+    single_loops_safe = cache[tool]["single_loops"]
+    if single_loops_safe:
+        single_loops = {}
+        for key, val in single_loops_safe.items():
+            single_loops[int(key)] = [i for i in val]
+    else:
+        single_loops = False
+    loops_safe = cache[tool]["loops"]
+    loops = []
+    for loop_safe in [loops_safe[str(j)] for j in range(len(loops_safe))]:
+        loop = []
+        circular = False
+        for key, val in loop_safe.items():
+            if key == "loop":
+                loop = [i for i in val]
+            else: # key == "circular"
+                circular = bool(val)
+        loops.append([loop, circular])
+    derived = bool(cache[tool]["derived"])
+    mapping_safe = cache[tool]["mapping"]
+    if derived:
+        mapping = {}
+        for key, val in mapping_safe.items():
+            mapping[int(key)] = val
+    else:
+        mapping = False
+    
+    return(True, single_loops, loops, derived, mapping)
+
+
+# store information in the cache
+def cache_write(tool, object, mesh, input_method, boundaries, single_loops,
+loops, derived, mapping):
+    # retrieve cache
+    if "LoopTools_cache" not in object:
+        object["LoopTools_cache"] = {}
+    cache = object["LoopTools_cache"]
+    # clear cache if cache was written by other version of the script
+    if "version" not in cache or \
+    cache["version"] != "".join(map(str, bl_info["version"])):
+        object["LoopTools_cache"] = {}
+        cache = object["LoopTools_cache"]
+    # clear cache of current tool
+    if tool in cache:
+        del cache[tool]
+    # prepare values to be saved as ID-property
+    input = ",".join([str(v.index) for v in mesh.vertices if \
+        v.select and not v.hide])
+    if mapping:
+        mapping_safe = dict([[str(key), val] for key, val in mapping.items()])
+    else:
+        mapping_safe = False
+    if single_loops:
+        single_loops_safe = dict([[str(key), val] for key, val in \
+            single_loops.items()])
+    else:
+        single_loops_safe = False
+    loops_safe = {}
+    for i, loop in enumerate(loops):
+        loops_safe[str(i)] = {"circular": loop[1], "loop": loop[0]}
+    # update cache
+    cache["version"] = "".join(map(str, bl_info["version"]))
+    cache[tool] = {"input": input, "input_method": input_method,
+        "boundaries": boundaries, "single_loops": single_loops_safe, 
+        "loops": loops_safe, "derived": derived, "mapping": mapping_safe}
+
+
+# calculates natural cubic splines through all given knots
+def calculate_cubic_splines(mesh_mod, tknots, knots):
+    # hack for circular loops
+    if knots[0] == knots[-1] and len(knots) > 1:
+        circular = True
+        k_new1 = []
+        for k in range(-1, -5, -1):
+            if k - 1 < -len(knots):
+                k += len(knots)
+            k_new1.append(knots[k-1])
+        k_new2 = []
+        for k in range(4):
+            if k + 1 > len(knots) - 1:
+                k -= len(knots)
+            k_new2.append(knots[k+1])
+        for k in k_new1:
+            knots.insert(0, k)
+        for k in k_new2:
+            knots.append(k)
+        t_new1 = []
+        total1 = 0
+        for t in range(-1, -5, -1):
+            if t - 1 < -len(tknots):
+                t += len(tknots)
+            total1 += tknots[t] - tknots[t-1]
+            t_new1.append(tknots[0] - total1)
+        t_new2 = []
+        total2 = 0
+        for t in range(4):
+            if t + 1 > len(tknots) - 1:
+                t -= len(tknots)
+            total2 += tknots[t+1] - tknots[t]
+            t_new2.append(tknots[-1] + total2)
+        for t in t_new1:
+            tknots.insert(0, t)
+        for t in t_new2:
+            tknots.append(t)
+    else:
+        circular = False
+    # end of hack
+    
+    n = len(knots)
+    if n < 2:
+        return False
+    x = tknots[:]
+    locs = [mesh_mod.vertices[k].co[:] for k in knots]
+    result = []
+    for j in range(3):
+        a = []
+        for i in locs:
+            a.append(i[j])
+        h = []
+        for i in range(n-1):
+            if x[i+1] - x[i] == 0:
+                h.append(1e-8)
+            else:
+                h.append(x[i+1] - x[i])
+        q = [False]
+        for i in range(1, n-1):
+            q.append(3/h[i]*(a[i+1]-a[i]) - 3/h[i-1]*(a[i]-a[i-1]))
+        l = [1.0]
+        u = [0.0]
+        z = [0.0]
+        for i in range(1, n-1):
+            l.append(2*(x[i+1]-x[i-1]) - h[i-1]*u[i-1])
+            if l[i] == 0:
+                l[i] = 1e-8
+            u.append(h[i] / l[i])
+            z.append((q[i] - h[i-1] * z[i-1]) / l[i])
+        l.append(1.0)
+        z.append(0.0)
+        b = [False for i in range(n-1)]
+        c = [False for i in range(n)]
+        d = [False for i in range(n-1)]
+        c[n-1] = 0.0
+        for i in range(n-2, -1, -1):
+            c[i] = z[i] - u[i]*c[i+1]
+            b[i] = (a[i+1]-a[i])/h[i] - h[i]*(c[i+1]+2*c[i])/3
+            d[i] = (c[i+1]-c[i]) / (3*h[i])
+        for i in range(n-1):
+            result.append([a[i], b[i], c[i], d[i], x[i]])
+    splines = []
+    for i in range(len(knots)-1):
+        splines.append([result[i], result[i+n-1], result[i+(n-1)*2]])
+    if circular: # cleaning up after hack
+        knots = knots[4:-4]
+        tknots = tknots[4:-4]
+    
+    return(splines)
+
+
+# calculates linear splines through all given knots
+def calculate_linear_splines(mesh_mod, tknots, knots):
+    splines = []
+    for i in range(len(knots)-1):
+        a = mesh_mod.vertices[knots[i]].co
+        b = mesh_mod.vertices[knots[i+1]].co
+        d = b-a
+        t = tknots[i]
+        u = tknots[i+1]-t
+        splines.append([a, d, t, u]) # [locStart, locDif, tStart, tDif]
+    
+    return(splines)
+
+
+# calculate a best-fit plane to the given vertices
+def calculate_plane(mesh_mod, loop, method="best_fit", object=False):
+    # getting the vertex locations
+    locs = [mathutils.Vector(mesh_mod.vertices[v].co[:]) for v in loop[0]]
+    
+    # calculating the center of masss
+    com = mathutils.Vector()
+    for loc in locs:
+        com += loc
+    com /= len(locs)
+    x, y, z = com
+    
+    if method == 'best_fit':
+        # creating the covariance matrix
+        mat = mathutils.Matrix([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0],
+            [0.0, 0.0, 0.0]])
+        for loc in locs:
+            mat[0][0] += (loc[0]-x)**2
+            mat[0][1] += (loc[0]-x)*(loc[1]-y)
+            mat[0][2] += (loc[0]-x)*(loc[2]-z)
+            mat[1][0] += (loc[1]-y)*(loc[0]-x)
+            mat[1][1] += (loc[1]-y)**2
+            mat[1][2] += (loc[1]-y)*(loc[2]-z)
+            mat[2][0] += (loc[2]-z)*(loc[0]-x)
+            mat[2][1] += (loc[2]-z)*(loc[1]-y)
+            mat[2][2] += (loc[2]-z)**2
+        
+        # calculating the normal to the plane
+        normal = False
+        try:
+            mat.invert()
+        except:
+            if sum(mat[0]) == 0.0:
+                normal = mathutils.Vector([1.0, 0.0, 0.0])
+            elif sum(mat[1]) == 0.0:
+                normal = mathutils.Vector([0.0, 1.0, 0.0])
+            elif sum(mat[2]) == 0.0:
+                normal = mathutils.Vector([0.0, 0.0, 1.0])
+        if not normal:
+            itermax = 500
+            iter = 0
+            vec = mathutils.Vector([1.0, 1.0, 1.0])

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list