0001"""
0002**geometric objects of the complex plane** as transformed by a given Moebius
0003tranformation
0004"""
0005
0006__Defs__ = ['mobTransform']
0007
0008__Classes__ = ['mobPointSets','mobMultiply','mobTranslate'
0009,'mobReciprocate','mobUnitCircle','mobFromFixed','mobMapCircles','mobRotate',
0010 'mobInverse']
0011
0012__all__= __Classes__ + __Defs__
0013
0014__doc_hints__={'m_type':'factory'}
0015
0016import pygeo.base.abstracts._complex as Complex
0017from pygeo.base.analytics.pygeomath import Mobius, Hermitian,matrixmultiply, sqrt, math_E,sin, inverse
0018
0019
0020class mobPointSets(Complex._zTransformation):
0021    """
0022*Mobius transformation* applied to the given **list of objects** of the complex plane
0023mapping the **3 (ordered) complex points** of the first point set
0024to the **3 (ordered) complex points** of the second point set. 
0025    
0026    inherits
0027    
0028        `_zTransformation`__
0029
0030__ class-base.abstracts._complex._zTransformation        
0031     
0032    """
0033
0034    __doc_hints__=  {'factory':'mobTransform',
0035                    'args':['[list of 3 points], [list of 3 points], [list of objects]']}
0036
0037    def __init__(self,v,w,elements,**kws):
0038        self.v=v
0039        self.w=w
0040        self.elements=[]
0041        for e in elements:
0042            for t in e:
0043                self.elements.append(t)
0044        args=self.v+self.w+self.elements
0045        for element in elements:
0046            if not element in args:
0047                args.append(element)
0048        Complex._zTransformation.__init__(self,*args,**kws)
0049        self.normal_form = kws.get('normal_form',False)
0050        self.init()
0051
0052    def _getMobius(self):
0053        p=self.v[0]
0054        q=self.v[1]
0055        r=self.v[2]
0056        p1=self.w[0]
0057        q1=self.w[1]
0058        r1=self.w[2]
0059        s=(p-r)/(q-r)
0060        s1=(p1-r1)/(q1-r1)
0061        a=s*p1-s1*q1
0062        b=p*q1*s1-p1*q*s
0063        c=s-s1
0064        d=p*s1-q*s
0065        try:
0066            self._mobius= Mobius([[a,b],[c,d]]).normalize()
0067            if self.normal_form:
0068                self._mobius.normal_form()
0069        except ValueError:
0070            self._mobius = Mobius([[0,0],[0,0]])
0071            print "degenerate Mobius matrix"
0072            return False
0073        return True
0074
0075class mobUnitCircle(Complex._zTransformation):
0076    """
0077*Mobius transformation* applied to the given **list of objects** of the complex plane 
0078mapping the given **complex circle** to the unit circle. 
0079
0080    inherits
0081    
0082        `_zTransformation`__
0083
0084__ class-base.abstracts._complex._zTransformation        
0085
0086    """
0087
0088    __doc_hints__=  {'factory':'mobTransform',
0089                    'args':['zcircle, [list of objects]']}
0090
0091    def __init__(self,zcircle,elements,**kws):
0092        self.zcircle=zcircle
0093        self.elements=[]
0094        for e in elements:
0095            for t in e:
0096                self.elements.append(t)
0097        args=[zcircle]+[elements]+self.elements
0098        for element in elements:
0099            if not element in args:
0100                args.append(element)
0101        Complex._zTransformation.__init__(self,*args,**kws)
0102        self.init()
0103
0104    def _getMobius(self):
0105        t_mat=Hermitian([[1,-self.zcircle._center],[0,1]])
0106        d_mat=Hermitian([[1.0/self.zcircle._radius,0],[0,1]])
0107        self._mobius= Mobius(matrixmultiply(d_mat,t_mat)).normalize()
0108        return True
0109
0110class mobMultiply(Complex._zTransformation):
0111    """
0112*Mobius transformation* multiplying the given **list of objects** of the complex plane
0113by the given **complex point**  
0114    
0115    inherits
0116    
0117        `_zTransformation`__
0118
0119__ class-base.abstracts._complex._zTransformation        
0120    
0121    """
0122
0123    __doc_hints__=  {'factory':'mobTransform',
0124                    'args':['zpoint, [list of objects]'],
0125                    'qualifier':'MULTIPLY'}
0126
0127    __opts__= Complex._zTransformation.__opts__[:] +['alt']
0128
0129    def __init__(self,z,elements,**kws):
0130        self.z=z
0131        self.elements=[]
0132        for e in elements:
0133            for t in e:
0134                self.elements.append(t)
0135        args=[z]+[elements]+self.elements
0136        for element in elements:
0137            if not element in args:
0138                args.append(element)
0139        Complex._zTransformation.__init__(self,*args,**kws)
0140        self.init()
0141
0142    def _getMobius(self):
0143        k=sqrt(self.z.toComplex())
0144        #try:
0145        self._mobius= Mobius([[k,0.],[0,1./k]]).normalize()
0146
0147        #except ZeroDivisionError:
0148        #    return False
0149        return True
0150
0151
0152
0153class mobTranslate(Complex._zTransformation):
0154    """
0155*Mobius transformation* translating the given **list of objects** of the complex plane
0156in the direction of the given **complex point**
0157   
0158    inherits
0159    
0160        `_zTransformation`__
0161
0162__ class-base.abstracts._complex._zTransformation        
0163   
0164   """
0165
0166    __doc_hints__=  {'factory':'mobTransform',
0167                    'args':['zpoint, [list of objects]'],
0168                    'qualifier':'TRANSLATE'}
0169
0170    __opts__= Complex._zTransformation.__opts__[:] +['alt']
0171
0172    def __init__(self,z,elements,**kws):
0173        self.z=z
0174        self.elements=[]
0175        for e in elements:
0176            for t in e:
0177                self.elements.append(t)
0178
0179        args=[z]+[elements]+self.elements
0180        for element in elements:
0181            if not element in args:
0182                args.append(element)
0183        Complex._zTransformation.__init__(self,*args,**kws)
0184        self.init()
0185
0186    def _getMobius(self):
0187        self._mobius= Mobius([[1,self.z.toComplex()],[0,1]]).normalize()
0188        return True
0189
0190class mobReciprocate(Complex._zTransformation):
0191    """
0192*Mobius transformation* reciprocating the given **list of objects** 
0193of the complex plane
0194    
0195    inherits
0196    
0197        `_zTransformation`__
0198
0199__ class-base.abstracts._complex._zTransformation        
0200    
0201    """
0202
0203    __doc_hints__=  {'factory':'mobTransform',
0204                    'args':['[list of objects]']}
0205
0206    def __init__(self,elements,**kws):
0207        self.elements=[]
0208        for e in elements:
0209            for t in e:
0210                self.elements.append(t)
0211        args=self.elements+[elements]
0212        for element in elements:
0213            if not element in args:
0214                args.append(element)
0215        Complex._zTransformation.__init__(self,*args,**kws)
0216        self.init()
0217
0218    def _getMobius(self):
0219        self._mobius= Mobius([[0.,1j],[1j,0.]])
0220        return True
0221
0222class mobFromFixed(Complex._zTransformation):
0223    """
0224*Mobius transformation* applied to the given **list of objects** of the complex plane 
0225with the given **2 complex points** as fixed points, and the given **numerical
0226value** as the transformation mulitplier
0227    
0228    inherits
0229    
0230        `_zTransformation`__
0231
0232__ class-base.abstracts._complex._zTransformation        
0233    
0234    """
0235
0236    __doc_hints__=  {'factory':'mobTransform',
0237                    'args':['zpoint1,zpoint2,float,[list of objects]']}
0238
0239    def __init__(self,f1,f2,k,elements,**kws):
0240        self.f1=f1
0241        self.f2=f2
0242        self.k=k
0243        self.elements=[]
0244        for e in elements:
0245            for t in e:
0246                self.elements.append(t)
0247
0248        args=[f1]+ [f2]+[k]+[elements]+self.elements
0249        for element in elements:
0250            if not element in args:
0251                args.append(element)
0252        Complex._zTransformation.__init__(self,*args,**kws)
0253        self.init()
0254
0255    def _getMobius(self):
0256        f1=self.f1
0257        f2=self.f2
0258        k=self.k
0259        A=f1-k*f2
0260        B=f1*f2*(k-1)
0261        C=1-k
0262        D=k*f1-f2
0263        self._mobius= Mobius([[A,B],[C,D]]).normalize()
0264        return True
0265
0266class mobMapCircles(Complex._zTransformation):
0267    """
0268*Mobius transformation* applied to the given **list of objects** of the complex plane mapping 
0269the interior of the first given **complex circle** to the exterior of the second 
0270given **complex circle**, 
0271    
0272    inherits
0273    
0274        `_zTransformation`__
0275
0276__ class-base.abstracts._complex._zTransformation        
0277    
0278    """
0279
0280    __doc_hints__=  {'factory':'mobTransform',
0281                    'args':['zcircle1, zcircle2, [list of objects]']}
0282
0283    def __init__(self,circle1,circle2,elements,**kws):
0284        self.circle1=circle1
0285        self.circle2=circle2
0286        self.elements=[]
0287        for e in elements:
0288            for t in e:
0289                self.elements.append(t)
0290        args=[circle1]+[circle2]+self.elements
0291        for element in elements:
0292            if not element in args:
0293                args.append(element)
0294        Complex._zTransformation.__init__(self,*args,**kws)
0295        self.normal_form = kws.get('normal_form',False)
0296        self.init()
0297
0298    def _getMobius(self):
0299        c1=self.circle1._center.toComplex()
0300        c2=self.circle2._center.toComplex()
0301        r1=self.circle1._radius
0302        r2=self.circle2._radius
0303        mat1=Mobius([[1,-c1],[0,1.]])
0304        mat2=Mobius([[0.,r1*r2],[1j,0]]).normalize()
0305        mat3=Mobius([[1,c2],[0,1.]])
0306        m=matrixmultiply(mat3,matrixmultiply(mat2,mat1))
0307        try:
0308            self._mobius=Mobius(m).normalize()
0309            if self.normal_form:
0310                self._mobius.normal_form()
0311        except ValueError:
0312            self._mobius = Mobius([[0,0],[0,0]])
0313            print "degenerate Mobius matrix"
0314            return False
0315        return True
0316
0317class mobRotate(Complex._zTransformation):
0318    """
0319*Mobius transformation* applied to the given **list of objects** of the complex plane
0320induced by the rotation of the Riemann sphere, with the stereographic projection of the 
0321given **complex point** as axis, by the given **numeric angle (in radians)**
0322    
0323    inherits
0324    
0325        `_zTransformation`__
0326
0327__ class-base.abstracts._complex._zTransformation        
0328    
0329    """
0330
0331    __doc_hints__=  {'factory':'mobTransform',
0332                    'args':['zpoint, float , [list of objects]']}
0333
0334    def __init__(self,zcenter,angle,elements,**kws):
0335        self.zcenter=zcenter
0336        self.angle=angle
0337        self.elements=[]
0338        for e in elements:
0339            for t in e:
0340                self.elements.append(t)
0341        args=[zcenter]+self.elements
0342        for element in elements:
0343            if not element in args:
0344                args.append(element)
0345        Complex._zTransformation.__init__(self,*args,**kws)
0346        self.normal_form = kws.get('normal_form',False)
0347        self.init()
0348
0349    def _getMobius(self):
0350        center=self.zcenter
0351        h_angle=self.angle/2.
0352        a=math_E**complex(0,h_angle)*center.mod2()+math_E**-(complex(0,h_angle))
0353        b=(0+2j)*sin(h_angle)*center
0354        c=-b.conjugate()
0355        d=a.conjugate()
0356        try:
0357            self._mobius=Mobius([[a,b],[c,d]]).normalize()
0358            if self.normal_form:
0359                self._mobius.normal_form()
0360        except ValueError:
0361            self._mobius = Mobius([[0,0],[0,0]])
0362            print "degenerate Mobius matrix"
0363            return False
0364        return True
0365
0366class mobInverse(Complex._zTransformation):
0367    """
0368*Mobius transformation* applied to the given **list of objects** of the complex plane 
0369defined by the matrix inverse of matrix representing the **given Mobius transformation**
0370    
0371    inherits
0372    
0373        `_zTransformation`__
0374
0375__ class-base.abstracts._complex._zTransformation        
0376    
0377    """
0378
0379    __doc_hints__=  {'factory':'mobTransform',
0380                    'args':['mobTransform, [list of objects]']}
0381
0382    def __init__(self,transform,elements,**kws):
0383        self.mobius=transform
0384        self.elements=[]
0385        for e in elements:
0386            for t in e:
0387                self.elements.append(t)
0388        args=[transform]+self.elements
0389        for element in elements:
0390            if not element in args:
0391                args.append(element)
0392        Complex._zTransformation.__init__(self,*args,**kws)
0393        self.normal_form = kws.get('normal_form',False)
0394        self.init()
0395
0396    def _getMobius(self):
0397        self._mobius=self.mobius._mobius.inverse()
0398        return True
0399
0400def mobTransform(*args,**kws):
0401    """
0402'class factory' function returns instance of object derived from the 
0403_zTransformation abstract class representing the Moebius tranformation defined
0404by its arguments, applied to a given list of objects of the complex plane
0405    """
0406    from pygeo.base.abstracts._element import method_get
0407    from pygeo.base.support.pygeoexceptions import Argument_Type_Error
0408    from pygeo.base.support.pygeoconstants import TRANSLATE, MULTIPLY
0409
0410    __sigs__=  [[list,list,list],
0411               [Complex._zCircle,list], [Complex._zPoint,list],
0412               [Complex._zPoint,list,float],
0413               [Complex._zCircle,Complex._zCircle,list],[list],
0414               [Complex._zPoint,float,list],
0415               [Complex._zPoint,Complex._zPoint,float,list]]
0416
0417    t,i = method_get(__sigs__,args)
0418
0419    if t is None:
0420       raise Argument_Type_Error(__sigs__,args)
0421    else:
0422        if i==0:
0423            if (len(t[0])==3 and len(t[1])==3):
0424                return mobPointSets(t[0],t[1],t[2],**kws)
0425        elif i==1:
0426            return mobUnitCircle(t[0],t[1],**kws)
0427        elif i==2:
0428            return mobMultiply(t[0],t[1],**kws)
0429        elif i==3:
0430            if t[2]==TRANSLATE:
0431                return mobTranslate(t[0],t[1],**kws)
0432            elif t[2]==MULTIPLY:
0433                return mobMultiply(t[0],t[1],**kws)
0434            else:
0435                raise Argument_Type_Error(__sigs__,args)
0436        elif i==4:
0437            return mobMapCircles(t[0],t[1],t[2],**kws)
0438        elif i==5:
0439            return mobReciprocate(t[0],**kws)
0440        elif i==6:
0441            return mobRotate(t[0],t[1],t[2],**kws)
0442        elif i==7:
0443            return mobFromFixed(t[0],t[1],t[2],t[3],**kws)
0444        else:
0445            raise Argument_Type_Error(__sigs__,args)