0001"""
0002**array of points** on a defined curve in space
0003"""
0004
0005__Def__ =       ['Curve']
0006
0007__Classes__ =   ['Bezier', 'PcCurve']
0008
0009__all__= __Classes__+ __Def__
0010
0011__doc_hints__={'m_type':'factory'}
0012
0013import pygeo.base.abstracts._real as Real
0014
0015from pygeo.base.support.pygeoconstants import *
0016from pygeo.base.analytics.pygeomath import reshape, array, vector, transpose,                                  matrixmultiply, ones
0018
0019
0020
0021class Bezier(Real._PointArray):
0022    """
0023*Bezier curve* with the **ordered list of points** as control points
0024    
0025    inherits
0026    
0027        `_PointArray`__
0028
0029__ class-base.abstracts._real._PointArray.html        
0030    
0031    """
0032    __doc_hints__=  {'factory':'Curve',
0033                    'args':['[list of points]']}
0034
0035    def __init__(self,inpoints,**kws):
0036        self.inpoints = inpoints
0037        Real._PointArray.__init__(self,*inpoints,**kws)
0038        coefs = self.getCoefs(len(self.inpoints)-1)
0039        bn = len(coefs)
0040        val=[]
0041        append=val.append
0042        for i in range (self.density+1):
0043            u=i/float(self.density)
0044            t =(1-u)
0045            for j in range(bn):
0046                cval = [coefs[j]*(t**(bn-j-1))*(u**j)]
0047                append(cval)
0048        self.U = reshape(array((val)),(self.density+1,bn))
0049        self.items =reshape(ones(3*len(self.inpoints),'d'),
0050                            (len(self.inpoints),3))
0051        self.density=kws.get('density',25)
0052        self.color=kws.get('color',RED)
0053        self.linewidth=kws.get('linewidth',.3)
0054        self.drawpoints=kws.get("drawpoints",False)
0055        self.drawcurve=kws.get("drawcurve",True)
0056        self.density+=1
0057        self.init()
0058
0059    def getCoefs(self,fact):
0060        facts = []
0061        coefs = []
0062        nom=1
0063        f_append=facts.append
0064        c_append=coefs.append
0065        for i in range(fact):
0066            nom*=(i+1)
0067            f_append(nom)
0068        c_append(1.0)
0069        for  i in range(1,fact):
0070            c_append(float(facts[fact-1]/(facts[i-1]*facts[fact-1-i])))
0071        c_append(1.0)
0072        return coefs
0073
0074    def findSelf(self):
0075        for i,inpoint in enumerate(self.inpoints):
0076            self.items[i] = inpoint
0077        for i,point in enumerate(self):
0078            r=matrixmultiply(
0079            transpose(self.items),self.U[i])
0080            point.set(vector(r))
0081        return True
0082
0083
0084class PcCurve(Real._PointArray):
0085    """
0086*cubic BSpline curve* with **1st and 2nd given points** as end points 
0087and **3rd and 4th points** as control points
0088    
0089    inherits
0090    
0091        `_PointArray`__
0092
0093__ class-base.abstracts._real._PointArray.html        
0094    
0095    """
0096    __doc_hints__=  {'factory':'Curve',
0097                    'args':['point1,point2,point3,point4']}
0098
0099    def __init__(self,p1,p2,p1u,p2u,**kws):
0100        self.p1=p1
0101        self.p2=p2
0102        self.p1u=p1u
0103        self.p2u=p2u
0104        self.M = array([[2.,-2.,1.,1.],[-3.,3.,-2.,-1.],[0.,0.,1.,0.],
0105                        [1.,0.,0.,0.]],'d')
0106        Real._PointArray.__init__(self,*[p1,p2,p1u,p2u],**kws)
0107        self.linewidth=kws.get('linewidth',.3)
0108        self.drawpoints=kws.get("drawpoints",False)
0109        self.drawcurve=kws.get("drawcurve",True)
0110        self.init()
0111
0112    def findSelf(self):
0113        pu1=self.p1u-self.p1
0114        pu2=self.p2-self.p2u
0115        B=array((self.p1,self.p2,pu1,pu2),'d')
0116        for i in range(self.density):
0117            u=i/float(self.density)
0118            U = array((u**3,u**2,u,1),'d')
0119            m= matrixmultiply(U,self.M)
0120            r = matrixmultiply(m,B)
0121            self.points[i].set(vector(r))
0122        return True
0123
0124def  Curve(*args,**kws):
0125    """
0126'class factory' function returns instance of object derived from 
0127the  _PointArray abstract class representing an array of points on 
0128a defined curve
0129    """
0130
0131    from pygeo.base.abstracts._element import method_get
0132    from pygeo.base.support.pygeoexceptions import Argument_Type_Error
0133
0134    __sigs__=[[list],[tuple],[vector,vector,vector,vector]]
0135
0136    t,i = method_get(__sigs__,args)
0137
0138    if t is None:
0139        raise Argument_Type_Error(__sigs__,args)
0140    else:
0141        if i==0 or i==1:
0142            return Bezier(t[0],drawcurve=True,**kws)
0143        elif i==2:
0144            return PcCurve(t[0],t[1],t[2],t[3],drawcurve=True,**kws)
0145        else:
0146            raise Argument_Type_Error(__sigs__,args)