[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [2134] contrib/py/scripts/addons/ curve_tools.py: added curve_tools.py to contrib/py/scripts/addons/ curve_tools.py
Brendon Murphy
meta.androcto1 at gmail.com
Mon Jul 18 13:54:20 CEST 2011
Revision: 2134
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=2134
Author: meta-androcto
Date: 2011-07-18 11:54:19 +0000 (Mon, 18 Jul 2011)
Log Message:
-----------
added curve_tools.py to contrib/py/scripts/addons/curve_tools.py
thanks to mackraken
Added Paths:
-----------
contrib/py/scripts/addons/curve_tools.py
Added: contrib/py/scripts/addons/curve_tools.py
===================================================================
--- contrib/py/scripts/addons/curve_tools.py (rev 0)
+++ contrib/py/scripts/addons/curve_tools.py 2011-07-18 11:54:19 UTC (rev 2134)
@@ -0,0 +1,1355 @@
+# #####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 #####
+
+bl_info = {
+ "name": "Curve Tools",
+ "author": "Zak",
+ "version": (0, 1, 5),
+ "blender": (2, 5, 8),
+ "api": 37702,
+ "location": "Properties > Object data",
+ "description": "Creates driven Lofts or Birails between curves",
+ "warning": "",
+ "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
+ "Scripts/Curve/Curve_Tools",
+ "tracker_url": "https://projects.blender.org/tracker/index.php?"\
+ "func=detail&aid=27720",
+ "category": "Add Curve"}
+
+### UPDATES
+#1.5
+
+#-Fixed birail function
+#-Added Curve Snap to W key specials menu.
+#-Removed some functions that arent needed and wrapped into the operators.
+#-nurbs with weights for loft and birail
+#-Panel Moved to view 3d tools
+#-inserted TODO comments
+#-tried to implement live tension and bias for Hermite interpolation by driving the mesh but
+#i dont know why, the code is executed all the time even if you dont change the variables.
+#-snap to curves affects all the curves on the scene
+#-i was able to preserve handle types when split or subdivide
+
+
+#1.4
+#-incorporate curve snap
+#assign a copy transform to helper
+#-nurbs implemented (in progress)
+
+import bpy
+from mathutils import *
+from bpy.props import *
+
+print("----------")
+
+
+### PROPERTIES
+class sprops(bpy.types.PropertyGroup):
+ pass
+
+
+bpy.utils.register_class(sprops)
+
+#bpy.selection will store objects names in the order they were selected
+bpy.selection=[]
+
+
+#dodriver a simple checker to chosse whether you want a driven mesh or not.
+bpy.types.Scene.dodriver = BoolProperty(name = "dodriver", default=False)
+
+#interpolation types
+myitems = (('0','Linear', ''),('1','Cubic',''),('2','Catmull',''), ('3','Hermite',''))
+bpy.types.Scene.intype = EnumProperty(name="intype", items = myitems, default='3')
+
+#number of steps and spans to be created
+bpy.types.Scene.steps = IntProperty(name="steps", default=12, min=2)
+bpy.types.Scene.spans = IntProperty(name="spans", default=12, min=2)
+
+#parameters for Hermite interpolation
+bpy.types.Scene.tension = FloatProperty(name = "tension", min=0.0, default=0.0)
+bpy.types.Scene.bias = FloatProperty(name = "bias", min=0.0, default = 0.5)
+
+#proportional birail
+bpy.types.Scene.proportional = BoolProperty(name="proportional", default=False)
+
+#this stores the result of calculating the curve length
+bpy.types.Scene.clen = FloatProperty(name="clen", default=0.0, precision=5)
+
+#minimun distance for merge curve tool
+bpy.types.Scene.limit = FloatProperty(name="limit", default=0.1, precision=3)
+
+
+### SELECT BY ORDER BLOCK
+
+#i dont know what to do with this. Im not using it yet.
+def selected_points(curve):
+
+ selp = []
+ for spl in curve.splines:
+ if spl.type=="BEZIER":
+ points = spl.bezier_points
+ for p in points:
+ if p.select_control_point:
+ selp.append(p)
+
+ elif spl.type=="NURBS":
+ points = spl.points
+ for p in points:
+ if p.select:
+ selp.append(p)
+ return selp
+
+#writes bpy.selection when a new object is selected or deselected
+#it compares bpy.selection with bpy.context.selected_objects
+
+def select():
+
+ #print(bpy.context.mode)
+ if bpy.context.mode=="OBJECT":
+ obj = bpy.context.object
+ sel = len(bpy.context.selected_objects)
+
+ if sel==0:
+ bpy.selection=[]
+ else:
+ if sel==1:
+ bpy.selection=[]
+ bpy.selection.append(obj)
+ elif sel>len(bpy.selection):
+ for sobj in bpy.context.selected_objects:
+ if (sobj in bpy.selection)==False:
+ bpy.selection.append(sobj)
+
+ elif sel<len(bpy.selection):
+ for it in bpy.selection:
+ if (it in bpy.context.selected_objects)==False:
+ bpy.selection.remove(it)
+
+ #on edit mode doesnt work well
+
+
+#executes selection by order at 3d view
+class Selection(bpy.types.Header):
+ bl_label = "Selection"
+ bl_space_type = "VIEW_3D"
+
+ def __init__(self):
+ #print("hey")
+ select()
+
+ def draw(self, context):
+ layout = self.layout
+ row = layout.row()
+ row.label("Sel: "+str(len(bpy.selection)))
+
+### GENERAL CURVE FUNCTIONS
+
+#distance between 2 points
+def dist(p1, p2):
+ return (p2-p1).magnitude
+
+#sets cursors position for debugging porpuses
+def cursor(pos):
+ bpy.context.scene.cursor_location = pos
+
+#cuadratic bezier value
+def quad(p, t):
+ return p[0]*(1.0-t)**2.0 + 2.0*t*p[1]*(1.0-t) + p[2]*t**2.0
+
+#cubic bezier value
+def cubic(p, t):
+ return p[0]*(1.0-t)**3.0 + 3.0*p[1]*t*(1.0-t)**2.0 + 3.0*p[2]*(t**2.0)*(1.0-t) + p[3]*t**3.0
+
+#gets a bezier segment's control points on global coordinates
+def getbezpoints(spl, mt, seg=0):
+ points = spl.bezier_points
+ p0 = points[seg].co * mt
+ p1 = points[seg].handle_right * mt
+ p2 = points[seg+1].handle_left * mt
+ p3 = points[seg+1].co * mt
+ return p0, p1, p2, p3
+
+#gets nurbs polygon control points on global coordinates
+def getnurbspoints(spl, mw):
+ pts = []
+ ws = []
+ for p in spl.points:
+ v = Vector(p.co[0:3])*mw
+ pts.append(v)
+ ws.append(p.weight)
+ return pts , ws
+
+#calcs a nurbs knot vector
+def knots(n, order, type=0):#0 uniform 1 endpoints 2 bezier
+
+ kv = []
+
+ t = n+order
+ if type==0:
+ for i in range(0, t):
+ kv.append(1.0*i)
+
+ elif type==1:
+ k=0.0
+ for i in range(1, t+1):
+ kv.append(k)
+ if i>=order and i<=n:
+ k+=1.0
+ elif type==2:
+ if order==4:
+ k=0.34
+ for a in range(0,t):
+ if a>=order and a<=n: k+=0.5
+ kv.append(floor(k))
+ k+=1.0/3.0
+
+ elif order==3:
+ k=0.6
+ for a in range(0, t):
+ if a >=order and a<=n: k+=0.5
+ kv.append(floor(k))
+
+ ##normalize the knot vector
+ for i in range(0, len(kv)):
+ kv[i]=kv[i]/kv[-1]
+
+ return kv
+
+#nurbs curve evaluation
+def C(t, order, points, weights, knots):
+ #c = Point([0,0,0])
+ c = Vector()
+ rational = 0
+ i = 0
+ while i < len(points):
+ b = B(i, order, t, knots)
+ p = points[i] * (b * weights[i])
+ c = c + p
+ rational = rational + b*weights[i]
+ i = i + 1
+
+ return c * (1.0/rational)
+
+#nurbs basis function
+def B(i,k,t,knots):
+ ret = 0
+ if k>0:
+ n1 = (t-knots[i])*B(i,k-1,t,knots)
+ d1 = knots[i+k] - knots[i]
+ n2 = (knots[i+k+1] - t) * B(i+1,k-1,t,knots)
+ d2 = knots[i+k+1] - knots[i+1]
+ if d1 > 0.0001 or d1 < -0.0001:
+ a = n1 / d1
+ else:
+ a = 0
+ if d2 > 0.0001 or d2 < -0.0001:
+ b = n2 / d2
+ else:
+ b = 0
+ ret = a + b
+ #print "B i = %d, k = %d, ret = %g, a = %g, b = %g\n"%(i,k,ret,a,b)
+ else:
+ if knots[i] <= t and t <= knots[i+1]:
+ ret = 1
+ else:
+ ret = 0
+ return ret
+
+#calculates a global parameter t along all control points
+#t=0 begining of the curve
+#t=1 ending of the curve
+
+def calct(obj, t):
+
+ spl=None
+ mw = obj.matrix_world
+ if obj.data.splines.active==None:
+ if len(obj.data.splines)>0:
+ spl=obj.data.splines[0]
+ else:
+ spl = obj.data.splines.active
+
+ if spl==None:
+ return False
+
+ if spl.type=="BEZIER":
+ points = spl.bezier_points
+ nsegs = len(points)-1
+
+ d = 1.0/nsegs
+ seg = int(t/d)
+ t1 = t/d - int(t/d)
+
+ if t==1:
+ seg-=1
+ t1 = 1.0
+
+ p = getbezpoints(spl,mw, seg)
+
+ coord = cubic(p, t1)
+
+ return coord
+
+ elif spl.type=="NURBS":
+ data = getnurbspoints(spl, mw)
+ pts = data[0]
+ ws = data[1]
+ order = spl.order_u
+ n = len(pts)
+ ctype = spl.use_endpoint_u
+ kv = knots(n, order, ctype)
+
+ coord = C(t, order-1, pts, ws, kv)
+
+ return coord
+
+#length of the curve
+def arclength(objs):
+ length = 0.0
+
+ for obj in objs:
+ if obj.type=="CURVE":
+ prec = 1000 #precision
+ inc = 1/prec #increments
+
+ ### TODO: set a custom precision value depending the number of curve points
+ #that way it can gain on accuracy in less operations.
+
+ #subdivide the curve in 1000 lines and sum its magnitudes
+ for i in range(0, prec):
+ ti = i*inc
+ tf = (i+1)*inc
+ a = calct(obj, ti)
+ b = calct(obj, tf)
+ r = (b-a).magnitude
+ length+=r
+
+ return length
+
+
+class ArcLengthOperator(bpy.types.Operator):
+
+ bl_idname = "curve.arc_length_operator"
+ bl_label = "Measures the length of a curve"
+
+ @classmethod
+ def poll(cls, context):
+ return context.active_object != None
+
+ def execute(self, context):
+ objs = context.selected_objects
+ context.scene.clen = arclength(objs)
+ return {'FINISHED'}
+
+### LOFT INTERPOLATIONS
+
+#objs = selected objects
+#i = object index
+#t = parameter along u direction
+#tr = parameter along v direction
+
+#linear
+def intl(objs, i, t, tr):
+ p1 = calct(objs[i],t)
+ p2 = calct(objs[i+1], t)
+
+ r = p1 + (p2 - p1)*tr
+
+ return r
+
+#tipo = interpolation type
+#tension and bias are for hermite interpolation
+#they can be changed to obtain different lofts.
+
+#cubic
+def intc(objs, i, t, tr, tipo=3, tension=0.0, bias=0.0):
+
+ ncurves =len(objs)
+
+ #if 2 curves go to linear interpolation regardless the one you choose
+ if ncurves<3:
+ return intl(objs, i, t, tr)
+ else:
+
+ #calculates the points to be interpolated on each curve
+ if i==0:
+ p0 = calct(objs[i], t)
+ p1 = p0
+ p2 = calct(objs[i+1], t)
+ p3 = calct(objs[i+2], t)
+ else:
+ if ncurves-2 == i:
+ p0 = calct(objs[i-1], t)
+ p1 = calct(objs[i], t)
+ p2 = calct(objs[i+1], t)
+ p3 = p2
+ else:
+ p0 = calct(objs[i-1], t)
+ p1 = calct(objs[i], t)
+ p2 = calct(objs[i+1], t)
+ p3 = calct(objs[i+2], t)
+
+
+ #calculates the interpolation between those points
+ #i used methods from this page: http://paulbourke.net/miscellaneous/interpolation/
+
+ if tipo==0:
+ #linear
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list