[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