0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022"""
0023abstract classes for geometric objects of the complex plane
0024"""
0025
0026
0027
0028
0029
0030
0031from pygeo.base.analytics._cposition import CPosition
0032from pygeo.base.support.pygeoconstants import CYAN,BLACK, BLUE,GREEN, YELLOW, RED
0033from pygeo.base.support.pygeoconstants import  ROUND, LINES, TINYFONT, DIAMOND
0034from pygeo.base.analytics.pygeomath import *
0035from pygeo.base.support.pygeoopts import COMPLEX_MAX
0036from pygeo.base.abstracts._element import Element,freepoints
0037import pygeo.base.drawing.zdraw as Z_Draw
0038
0039
0040class _zPoint(CPosition,Element,Z_Draw.zdrawPoint):
0041    """ a zero dimensional object with a defined postion on the complex plane
0042
0043inherits:  Element__ , CPosition__ , zdrawPoint__
0044
0045defining instance attributes 
0046
0047    - real: the real coordinate
0048    - imag: the imaginary coordinate
0049
0050__ class-base.abstracts._element.Element.html
0051__ class-base.analytics._cposition.CPosition.html
0052__ class-base.drawing.zdraw.zdrawPoint.html
0053    """
0054
0055    __opts__= Element.__opts__[:] + ["pointsize","tracewidth","tracecolor",
0056                                    "maxtrace","mintrace", "fontsize",
0057                                    "fontcolor","fontXofffset","fontYofffset","tracecurve","style"]
0058
0059    def __init__(self,*args,**kws):
0060        """intialize attributes, with keywords arguments or defaults"""
0061
0062        self.Not_null = True
0063        self._pos=None
0064        Element.__init__(self,*args,**kws)
0065        self.color = kws.get("color",CYAN)
0066        self.pointsize=kws.get("pointsize",.1)
0067        self.style=kws.get("style",ROUND)
0068        if self.label:
0069            self.fontsize=kws.get("fontsize",TINYFONT)
0070            self.fontcolor=kws.get("fontcolor",BLACK)
0071            self.fontXoffset=kws.get("fontXoffset",self.pointsize/10.+3)
0072            self.fontYoffset=kws.get("fontYoffset",self.pointsize/10.+3)
0073        if self.trace:
0074            self.tmparray=CPosition()
0075            self.tmparray.set(self)
0076            self.tracecurve=kws.get("tracecurve",True)
0077            self.mintrace=kws.get("mintrace",.0001)
0078            self.maxtrace=kws.get("maxtrace",50.)
0079            self.tracewidth=kws.get("tracewidth",self.pointsize/2.0)
0080            self.tracecolor=kws.get("tracecolor",self.color)
0081        self.deps=[]
0082
0083    def __description(self, precision):
0084        if self.real != 0.:
0085            return self.__class__.__name__ + "(%.*g%+.*gj)"%(precision,
0086                                             self.real, precision, self.imag)
0087        else:
0088            return self.__class__.__name__ + "%.*gj"%(precision, self.imag)
0089
0090    def __repr__(self):
0091        return self.__description(self.PREC_REPR)
0092
0093    def __str__(self):
0094        return self.__description(self.PREC_STR)
0095
0096    def transform(self,mat,zpoint):
0097        """the Mobius transformation represented by a given complex 2x2 matrix, assigned
0098        to the given point"""
0099        mat = matrixmultiply(mat,self.homogenous())
0100        zpoint.toC(mat)
0101
0102   
0103   
0104        return True
0105
0106
0107    def uRotate(self,ucenter,angle):
0108        """transform cuurent position as the effect of a rotation of the Riemann sphere
0109        around the given point as axis and the given angle"""
0110
0111        h_angle=angle/2.
0112        cs=cos(h_angle)
0113        sn=sin(h_angle)
0114        a=complex(cs,ucenter.z*sn)
0115        b=complex(-ucenter.y,ucenter.x)*sn
0116        c=-b.conjugate()
0117        d=a.conjugate()
0118        mat1=([[a,b],[c,d]])
0119        mat2=self.homogenous()
0120        self.toC(matrixmultiply(mat1,mat2))
0121        return True
0122
0123    def toC(self,h_array):
0124        """set the position as te projection of a given homogenous complex number to the
0125        complex plane"""
0126
0127        self.set(h_array[0]/h_array[1])
0128        return True
0129
0130    def uVector(self):
0131        """return the vector represnting hte prjojection of the zpoint to the Riemann sphere"""
0132
0133        modplus=self.mod2()+1.
0134        modminus=self.mod2()-1.
0135        xy=2*self/modplus
0136        z=modminus/modplus
0137        return vector(xy.real,xy.imag,z)
0138
0139    def to_uSphere(self,upoint):
0140        """set the given point to the projection of the zpoint to the Riemann sphere"""
0141
0142        upoint.set(self.uVector())
0143        return True
0144
0145    def from_hermitian(self,h):
0146        """set the position on the zplane from the Hermitian matrix representation of the point"""
0147
0148        try:
0149            self.set(-h.C/h.A)
0150        except ZeroDivisionError:
0151            return self.set(CPosition(COMPLEX_MAX,COMPLEX_MAX))
0152    def setHermitian(self):
0153        """set the Hermitian matrix representation of the point"""
0154
0155        A=1
0156        C=-self
0157        B=C.conjugate()
0158        D = B*C
0159        self._hermitian = Hermitian([[A,B],[C,D]])
0160        return self._hermitian
0161
0162
0163class _zFreePosition(_zPoint):
0164    """ an O dimensional object of the complex plane that can picked and moved, either
0165freely on the plane or constrained to a given geoemtric object of the plane. 
0166             
0167inherits:  
0168 
0169    class. `_zPoint`__ 
0170
0171defining instance attributes 
0172
0173    - real: the real coordinate
0174    - imag: the imaginary coordinate
0175
0176__ class-base.abstracts._complex._zPoint.html
0177    """
0178
0179    def __init__(self,*args,**kws):
0180        """intialize attributes, with keywords arguments or defaults"""
0181
0182        _zPoint.__init__(self,*args,**kws)
0183        self.color = kws.get("color",BLUE)
0184        self.initcolor=self.color
0185        self.pointsize=kws.get("pointsize",.12)
0186        self.style=ROUND
0187        self.initpointsize=self.pointsize
0188        self.initpos=CPosition(self.real,self.imag)
0189        freepoints.append(self)
0190        self.dependants=[]
0191
0192    def _add_dependant(self,e):
0193        """ called when the intilization and registration of an object
0194        determines it to be dependant of an instance derived from  _zFreePosoition"""
0195
0196        self.dependants.append(e)
0197
0198    def reset(self):
0199        """Reset to position of start-up input"""
0200        self.pointsize=self.initpointsize
0201        self.drawcolor = self.initcolor
0202        self.set(self.initpos)
0203        _zPoint.update(self)
0204
0205
0206class _zLine(Element,Z_Draw.zdrawLine):
0207    """a straight line of the complex plane , representing a complex circle of 
0208infinite radius
0209             
0210inherits 
0211
0212    Element__ , zdrawLine__  
0213
0214defining instance attributes 
0215    
0216    - p1: a complex point on the line 
0217    - p2  a complex point on the line 
0218    - _hermitian: the hermitian matrix associated with the line
0219
0220__ class-base.abstracts._element.Element.html
0221__ class-base.drawing.zdraw.zdrawLine.html
0222    
0223    """
0224
0225    __opts__ = _zPoint.__opts__[:]+["linewidth","label_ratio","show_normal"]
0226    __opts__.remove("pointsize")
0227
0228    def __init__(self,*args,**kws):
0229        """intialize attributes, with keywords arguments or defaults"""
0230
0231        Element.__init__(self,*args,**kws)
0232        self.precision = kws.get("precision",40)
0233        self.linewidth=kws.get("linewidth",.02)
0234        self.color = kws.get("color",GREEN)
0235        self.show_normal=kws.get("show_normal",False)
0236        self.normal_width=kws.get("normal_width",.02)
0237        self.bounds1 = None
0238        self.bounds2 = None
0239        if self.label:
0240            self.fontsize=kws.get("fontsize",TINYFONT)
0241            self.fontcolor=kws.get("fontcolor",BLACK)
0242            self.fontXoffset=kws.get("fontXoffset",self.pointsize/10.+3)
0243            self.fontYoffset=kws.get("fontYoffset",self.pointsize/10.+3)
0244            self.lratio=kws.get("label_ratio",.5)
0245        self.p1=_zPoint(append=False)
0246        self.p2=_zPoint(append=False)
0247
0248    def findSelf(self):
0249        self.set_hermitian_from_points()
0250        return True
0251
0252    def __description(self):
0253        if hasattr(self,'p1'):
0254            return self.__class__.__name__ + "(%s,%s)" %(self.p1,self.p2)
0255        else:
0256            return self.__class__.__name__ + "(%s,%s)"
0257
0258    def __repr__(self):
0259        return self.__description()
0260
0261    def __str__(self):
0262        return self.__description()
0263
0264    def transform(self,mat,h_circle):
0265        """ transforms the Hermitian matrix defining the line by the given Mobius transformation
0266        matrix"""
0267
0268        t1=inverse(mat)
0269        h_circle._hermitian =self._hermitian.transform(mat)
0270        h_circle.set_radius_from_hermitian()
0271        return True
0272
0273    def to_uSphere(self,uCircle):
0274        """ sets the given ucircle to the projection of the line to the Riemann sphere"""
0275
0276        h=self._hermitian
0277        a=h.B+h.C
0278        b=(h.B-h.C)*1j
0279        c=h.D-h.A
0280        d=h.D+h.A
0281        v=vector(a.real,b.real,-c)
0282        try:
0283            uCircle._u.set(v.norm())
0284            uCircle._d = d =  d/v.mag*-1.
0285        except ZeroDivisionError:
0286            uCircle._u.set(vector(0,0,1))
0287            uCircle._d=0
0288        u=uCircle._u
0289        uCircle.set_s_from_u(u)
0290        uCircle._center.set(u*d)
0291        pdist = uCircle._center.mag2
0292        uCircle._radiusSquared=1-pdist
0293        
0294        uCircle._radius=sqrt(uCircle._radiusSquared)
0295        
0296        
0297        return True
0298
0299    def getDirection(self):
0300        """the normalized direction vector of the line"""
0301
0302        v = self.p2-self.p1
0303        v /= v.mod()
0304        return v
0305
0306    def getAngle(self):
0307        """the angle of the line with the real axis"""
0308
0309        return self.getDirection().arg()
0310
0311    def getNormal(self):
0312
0313        c = CPosition(self.p2.imag-self.p1.imag,self.p1.real-self.p2.real)
0314        c /= c.mod()
0315        return c
0316
0317    def getDistance(self):
0318        n=self.getNormal()
0319        return n.real*self.p1.real + n.imag*self.p1.imag
0320
0321    def set_hermitian_from_points(self):
0322        d=self.getNormal().arg()
0323        n = CPosition( cos(d),sin(d))
0324        self._hermitian = Hermitian([[0,n.conjugate()],[n,-self.getDistance()*2]])
0325
0326
0327class _zCircle(Element,Z_Draw.zdrawCircle):
0328    """ the set of points the complex plane that are equidistant from a given point 
0329of the plane
0330
0331inherits:  
0332
0333    Element__ , zdrawCircle__                
0334
0335
0336defining instance attributes 
0337    
0338    - _center: the complex point on circle's center
0339    - _cpoint: a complex point on circle circumference
0340    - _hermitian: the hermitian matrix associated with the circle
0341    - _radius: the circle's radius 
0342    - _radiusSquared: the square of the circle's radius 
0343
0344__ class-base.abstracts._element.Element.html
0345__ class-base.drawing.zdraw.zdrawCircle.html
0346   
0347    """
0348
0349    __opts__= Element.__opts__[:] + ["style","linewidth","precision","fixed","circle_type","O"]
0350
0351    def __init__(self,*args,**kws):
0352        """intialize attributes, with keywords arguments or defaults"""
0353
0354        self.precision = kws.get("precision",40)
0355        self.style = kws.get("style",LINES)
0356        self.linewidth = kws.get("linewidth",.02)
0357        self.show_normal=False
0358        self._u=vector(0,0,1)
0359        self._s=CPosition(1,0)
0360        self._radiusSquared=0
0361        self._radius=0
0362        self._d=0
0363        self._center=_zPoint(append=False)
0364        self._cpoint=_zPoint(append=False)
0365        Element.__init__(self,*args,**kws)
0366        self.color = kws.get("color",BLUE)
0367        O = kws.get("O","+")
0368        if O=="+":
0369           self.a=1
0370        else:
0371           self.a=-1
0372
0373    def findSelf(self):
0374        self.set_hermitian_from_radius()
0375        return True
0376
0377    def __description(self):
0378        return self.__class__.__name__ + "(%s,%.5f)" %(self._center,self._radius)
0379
0380    def __repr__(self):
0381        return self.__description()
0382
0383    def __str__(self):
0384        return self.__description()
0385
0386    def transform(self,mat,h_circle):
0387        t1=inverse(mat)
0388        h_circle._hermitian=self._hermitian.transform(mat)
0389        h_circle.set_radius_from_hermitian()
0390        return True
0391
0392    def to_uSphere(self,uCircle):
0393        h=self._hermitian
0394        a=h.B+h.C
0395        b=(h.B-h.C)*1j
0396        c=h.D-h.A
0397        d=h.D+h.A
0398        v=vector(a.real,b.real,-c)
0399        try:
0400           uCircle._u.set(v.norm())
0401           uCircle._d = d =  d/v.mag*-1
0402        except ZeroDivisionError:
0403           uCircle._u.set(vector(0,0,1))
0404           uCircle._d=0
0405        u=uCircle._u
0406        uCircle.set_s_from_u(u)
0407        uCircle._center.set(u*d)
0408        pdist = uCircle._center.mag2
0409        uCircle._radiusSquared=1-pdist
0410        try:
0411            uCircle._radius=rad=sqrt(uCircle._radiusSquared)
0412        except ValueError:
0413            uCircle._radius=rad=0
0414        uCircle._cpoint.set(uCircle._s*rad+uCircle._center)
0415        return True
0416
0417    def set_radius_from_hermitian(self):
0418        h=self._hermitian
0419        try:
0420            self._center.set(-h.C/h.A)
0421            fact=h.D/h.A
0422            self._radiusSquared = absolute(self._center.mod2() - fact)
0423            self._radius = sqrt(self._radiusSquared)
0424        except ZeroDivisionError:
0425            pass
0426
0427    def set_radius_from_cpoint(self):
0428        self._radiusSquared=self._center.distanceSquared(self._cpoint)
0429        self._radius=sqrt(self._radiusSquared)
0430
0431    def set_hermitian_from_radius(self):
0432        center=self._center
0433        A=self.a
0434        C=center*-A
0435        B=C.conjugate()
0436        D=(center*center.conjugate()-self._radiusSquared)*A
0437
0438        self._hermitian= Hermitian([[A,B],[C,D]])
0439
0440
0441class _zPointArray(Element,Z_Draw.zdrawArray):
0442    """an array of points on the complex plane with a defined 
0443geometric relationship
0444
0445inherits  
0446    
0447    Element__ , zdrawArray__ 
0448
0449defining instance attributes 
0450    
0451    zpoints: positioned complex points of the array
0452
0453__ class-base.abstracts._element.Element.html
0454__ class-base.drawing.zdraw.zdrawArray.html
0455     
0456     """
0457
0458    __opts__= Element.__opts__[:] + ["pointsize","density","style"]
0459
0460    def __init__(self,*args,**kws):
0461        """intialize attributes, with keywords arguments or defaults"""
0462
0463        Element.__init__(self,*args,**kws)
0464        self.density=kws.get('density',50)
0465        self.pointsize=kws.get('pointsize',.1)
0466        self.style=kws.get("style",DIAMOND)
0467        self.color = kws.get("color",CYAN)
0468        self.zpoints=[]
0469        self.deps=[]
0470
0471    def __iter__(self):
0472        for zpoint in self.zpoints:
0473            yield zpoint
0474
0475    def __len__(self):
0476        return len(self.zpoints)
0477
0478    def init(self):
0479        p_append=self.zpoints.append
0480        i=0
0481        while i < self.density:
0482            n=_zPoint(pointsize=self.pointsize,color=self.
0483                 color,level=self.level,append=False,style=self.style)
0484            n.init()
0485            p_append(n)
0486            i+=1
0487        Element.init(self)
0488
0489
0490class _zLineArray(Element,Z_Draw.zdrawArray):
0491    """an array of lines on the complex plane with a defined geometric relationship
0492
0493inherits  
0494
0495    Element__ ,  zdrawArray__
0496
0497defining instance attributes 
0498    
0499    zlines: positioned lines of the complex plane
0500
0501__ class-base.abstracts._element.Element.html
0502__ class-base.drawing.zdraw.zdrawArray.html
0503
0504    """
0505
0506    __opts__= Element.__opts__[:] + ["density","linewidth"]
0507
0508    def __init__(self,*args,**kws):
0509        """intialize attributes, with keywords arguments or defaults"""
0510
0511        Element.__init__(self,*args,**kws)
0512        self.density=kws.get('density',50)
0513        self.linewidth=kws.get('linewidth',.015)
0514        self.color = kws.get("color",YELLOW)
0515        self.zlines=[]
0516        self.deps=[]
0517
0518    def __iter__(self):
0519        for zline in self.zlines:
0520            yield zline
0521
0522    def __len__(self):
0523        return len(self.zlines)
0524
0525    def init(self):
0526        p_append=self.zlines.append
0527        i=0
0528        while i < self.density:
0529            n=_zLine(linewidth=self.linewidth,color=self.
0530                color,level=self.level,append=False)
0531            n.init()
0532            p_append(n)
0533            i+=1
0534        Element.init(self)
0535
0536
0537class _zCirclePencil(Element,Z_Draw.zdrawArray):
0538    """an array of circles on the complex plane with a defined geometric relationship
0539
0540inherits  
0541
0542    Element__ , zdrawArray__ 
0543
0544defining instance attributes 
0545    
0546    zcircles: positioned circles of the complex plane
0547
0548__ class-base.abstracts._element.Element.html
0549__ class-base.drawing.zdraw.zdrawArray.html
0550    
0551    """
0552
0553    __opts__= Element.__opts__[:] + ["linewidth","style","density","precision"]
0554
0555    def __init__(self,*args,**kws):
0556        """intialize attributes, with keywords arguments or defaults"""
0557
0558        self.precision=kws.get("precision",70)
0559        self.linewidth=kws.get("linewidth",.015)
0560        self.style=kws.get("style",LINES)
0561        self.density=kws.get("density",30)
0562        Element.__init__(self,*args,**kws)
0563        self.color=kws.get("color",RED)
0564        self.deps=[]
0565        self.zcircles=[]
0566
0567    def __len__(self):
0568        return len(self.circles)
0569
0570    def __iter__(self):
0571        for zcircle in self.zcircles:
0572            yield zcircle
0573
0574    def init(self):
0575        c_append=self.zcircles.append
0576        i=0
0577        while i < self.density:
0578            n=_zCircle(color=self.color,level=self.level,
0579                   precision=self.precision,style=self.style,append=False)
0580            n.init()
0581            c_append(n)
0582            i+=1
0583        Element.init(self)
0584
0585
0586class _zTransformation(Element,Z_Draw.zdrawArray):
0587    """a Mobius transformation of geometric objects of the complex plane
0588
0589inherits  
0590
0591    Element__ ,  zdrawArray__
0592
0593defining instance attributes 
0594    
0595    _mobius: the Mobius tranformation matrix defining the transformation
0596
0597__ class-base.abstracts._element.Element.html
0598__ class-base.drawing.zdraw.zdrawArray.html
0599   
0600   """
0601
0602    __opts__= Element.__opts__[:] + ["normal_from"]
0603
0604    def __init__(self,*args,**kws):
0605        """intialize attributes, with keywords arguments or defaults"""
0606
0607        Element.__init__(self,*args,**kws)
0608        self.color = kws.get("color",None)
0609        self.level = kws.get("level",None)
0610        self.deps=[]
0611
0612    def findSelf(self):
0613        if self._getMobius():
0614            for e,t in zip(self.elements,self.transforms):
0615                e.transform(self._mobius,t)
0616            return True
0617        else:
0618            return False
0619
0620    def __iter__(self):
0621        for transform in self.transforms:
0622            yield transform
0623
0624    def _getMobius(self):
0625        pass
0626
0627    def init(self):
0628        self.transforms=[]
0629        for e in self.elements:
0630            if self.color:
0631                color=self.color
0632            else:
0633                color=e.color
0634            if self.level:
0635                level=self.level
0636            else:
0637                level=e.level
0638            if isinstance(e,_zPoint):
0639                self.transforms.append(_zPoint(pointsize=e.pointsize,
0640                                       color=color,level=level,export = self.export,
0641                                       style=e.style,append=False))
0642            elif isinstance(e,_zCircle):
0643                self.transforms.append(_zCircle(linewidth=e.linewidth,
0644                                       color=color,level=level,export = self.export,
0645                                       append=False))
0646            elif isinstance(e,_zLine):
0647                self.transforms.append(_zCircle(linewidth=e.linewidth,
0648                                       color=color,level=level,export = self.export,
0649                                       append=False))
0650            elif isinstance(e,_zCirclePencil):
0651                for circle in e:
0652                    self.transforms.append(_zCircle(linewidth=e.linewidth,
0653                                          color=color,level=level,export = self.export,
0654                                          append=False))
0655        for t in self.transforms:
0656            t.init()
0657        Element.init(self)
0658
0659
0660__author__ = "Arthur Siegel <ajsiegel@optonline.com>"
0661__date__ = "Date: 2006-02-02 "
0662__revision__ = "Revision: a1"
0663__url__ = "URL: http://sourceforge.net/projects/pygeo"
0664__copyright__ ="GPL <http://www.opensource.org/licenses/gpl-license.php>"