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>"