0001###########################################################################
0002# PyGeo - a dynamic geometry toolkit
0003# Copyright (C) 2005 Arthur Siegel (ajsiegel@optonline.com)
0004#
0005# This library is free software; you can redistribute it and/or
0006# modify it under the terms of the GNU Lesser General Public
0007# License as published by the Free Software Foundation; either
0008# version 2.1 of the License, or (at your option) any later version.
0009#
0010# This library is distributed in the hope that it will be useful,
0011# but WITHOUT ANY WARRANTY; without even the implied warranty of
0012# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013# Lesser General Public License for more details.
0014#
0015# You should have received a copy of the GNU Lesser General Public
0016# License along with this library; if not, write to the Free Software
0017# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0018#
0019#PyGeo homepage: http://pygeo.sourceforge.net
0020###########################################################################
0021
0022
0023"""
0024abstract classes for geometric objects of real space
0025"""
0026
0027# PyGeo modules
0028from pygeo.base.analytics._position3 import Position3
0029from pygeo.base.support.pygeoconstants import CYAN,BLACK, BLUE,GREEN, RED, WHITE, MAGENTA ,LIGHTGRAY
0030from pygeo.base.support.pygeoconstants import  ROUND, LINES, NORMALFONT
0031from pygeo.base.support.pygeoopts import EPS
0032from pygeo.base.analytics.pygeomath import *
0033
0034import pygeo.base.drawing.vdraw as Draw
0035
0036from pygeo.base.abstracts._element import Element,freepoints
0037
0038
0039class _Point(Position3,Element,Draw.drawPoint):
0040    """  a O dimensional object with a defined position in space. 
0041    
0042inherits
0043    
0044    Element__ , Position3__ , drawPoint__
0045    
0046defining instance attributes 
0047    
0048    - x: x coord
0049    - y: y coord
0050    - z: z coord
0051    
0052__ class-base.abstracts._element.Element.html
0053__ class-base.analytics._position3.Position3.html
0054__ class-base.drawing.vdraw.drawPoint.html
0055    
0056    """
0057    __opts__= Element.__opts__[:] + ["pointsize","tracewidth","tracecolor",
0058                                    "maxtrace","mintrace", "fontsize",
0059                                    "fontcolor","fontXofffset","fontYofffset","style"]
0060
0061    def __init__(self,*args,**kws):
0062        """intialize attributes, with keywords arguments or defaults"""
0063
0064        #inherit geometric intelligence of the Position3 class
0065        Position3.__init__(self,*args)
0066
0067        self.Not_null = True
0068        self._pos=None
0069
0070        #inherit default attributes and functions common to all PyGeo elements. Overide
0071        #defaults where desired.
0072        Element.__init__(self,*args,**kws)
0073
0074        # override defalut color of Element clasas
0075        self.color = kws.get("color",CYAN)
0076
0077        #set defaults for keyword arguments specific to Points and derived classes.
0078        self.pointsize=kws.get("pointsize",.5)
0079        self.style=kws.get("style",ROUND)
0080
0081        if self.label:
0082            self.fontsize=kws.get("fontsize",NORMALFONT)
0083            self.fontcolor=kws.get("fontcolor",BLACK)
0084            self.fontXoffset=kws.get("fontXoffset",self.pointsize/10.+3)
0085            self.fontYoffset=kws.get("fontYoffset",self.pointsize/10.+3)
0086        if self.trace:
0087            self.tmparray=Position3()
0088            self.tmparray.set(self)
0089            self.mintrace=kws.get("mintrace",.1)
0090            self.maxtrace=kws.get("maxtrace",200.)
0091            self.tracewidth=kws.get("tracewidth",self.pointsize/2.0)
0092            self.tracecolor=kws.get("tracecolor",self.color)
0093        self.deps=[]
0094
0095    def __eq__(self, other):
0096        """ tests for equality between points"""
0097
0098        if hasattr(other,'x'):
0099            return  ((abs(self.x - other.x)) < EPS and
0100                    (abs(self.y - other.y)) < EPS
0101                     and (abs(self.z-other.z)) < EPS)
0102        else:
0103            return id(self)== id(other)
0104
0105
0106class _FreePosition(_Point):
0107    """  a O dimensional object which can be picked and moved through the scene 
0108display interface.
0109             
0110inherits  
0111    
0112    `_Point`__ 
0113
0114defining instance attributes 
0115    
0116    - x: x coord
0117    - y: y coord
0118    - z: z coord
0119
0120__ class-base.abstracts._real._Point.html 
0121    
0122    """
0123
0124    def __init__(self,*args,**kws):
0125        """intialize attributes, with keywords arguments or defaults"""
0126
0127        _Point.__init__(self,*args,**kws)
0128        self.color = kws.get("color",BLUE)
0129        self.initcolor=self.color
0130        self.pointsize=kws.get("pointsize",.7)
0131        self.style=ROUND
0132        self.initpointsize=self.pointsize
0133        self.initvector=Position3()
0134        self.initvector.set(self)
0135        freepoints.append(self)
0136        self.dependants=[self]
0137
0138    def _add_dependant(self,e):
0139        """ called when the intilization and registration of an object
0140        determines it to be dependant of an instance derived from  _FreePosoition"""
0141
0142        self.dependants.append(e)
0143
0144    def reset(self):
0145        """Reset to position of start-up input"""
0146
0147        self.pointsize=self.initpointsize
0148        self.color = self.initcolor
0149        self.set(self.initvector)
0150        _Point._redraw(self)
0151
0152
0153class _Line(Element,Draw.drawLine):
0154    """ a 1 dimensional object representing "breathless length"
0155    
0156inherits
0157    
0158    Element__ , drawLine__
0159    
0160defining instance attributes 
0161    
0162    - p1: a point on the line 
0163    - p2: a point on the line
0164
0165__ class-base.abstracts._element.Element.html
0166__ class-base.drawing.vdraw.drawLine.html
0167    """
0168
0169    __opts__ = _Point.__opts__[:]+["linewidth","label_ratio","show_normal","seg"]
0170    __opts__.remove("pointsize")
0171
0172    def __init__(self,*args,**kws):
0173        """intialize attributes, with keywords arguments or defaults"""
0174
0175        Element.__init__(self,*args, **kws)
0176        self.linewidth=kws.get("linewidth",.2)
0177        self.color = kws.get("color",GREEN)
0178        self.show_normal=kws.get("show_normal",False)
0179        self.normal_width=kws.get("normal_width",.4)
0180        self.seg=kws.get('seg',False)
0181        self.bounds1=None
0182        self.bounds2=None
0183        if self.label:
0184           self.fontsize=kws.get("fontsize",NORMALFONT)
0185           self.fontcolor=kws.get("fontcolor",BLACK)
0186           self.lratio=kws.get("label_ratio",.5)
0187           self.fontXoffset=kws.get("fontXoffset",self.linewidth/10+1)
0188        self.fontYoffset=kws.get("fontYoffset",self.linewidth/10+1)
0189        self.p1=_Point(append=False)
0190        self.p2=_Point(append=False)
0191        if self.trace:
0192           self.tracewidth=kws.get("tracewidth",self.linewidth)
0193           self.tracecolor=kws.get("tracecolor",self.color)
0194        self.deps=[]
0195
0196    def __repr__(self):
0197        return self.__class__.__name__ + "(" + str(self.p1) +"," + str(self.p2) + ")"
0198
0199    def transform(self,mat,obj):
0200        """ transform the point attributes defining the line by the given
0201        4x4 transformation matrix"""
0202
0203        self.p1.transform(mat,obj.p1)
0204        self.p2.transform(mat,obj.p2)
0205        if self.bounds1:
0206            obj.bounds1=_Point()
0207            self.bounds1.transform(mat,obj.bounds1)
0208        else:
0209            obj.bounds1=None
0210        if self.bounds2:
0211            obj.bounds2=_Point()
0212            self.bounds2.transform(mat,obj.bounds2)
0213        else:
0214            obj.bounds2=None
0215
0216    def length(self):
0217        """the length of the segment of the line connecting the p1 and p2 attributes"""
0218
0219        return self.p1.distance(self.p2)
0220
0221    def lengthSquared(self):
0222        """the square of the length of the segment of the line connecting the p1 
0223        and p2 attributes"""
0224
0225        return self.p1.distanceSquared(self.p2)
0226
0227    def getDirection(self):
0228        """unit vector of the line direction"""
0229
0230        try:
0231            return (self.p2-self.p1).norm()
0232        except ZeroDivisionError:
0233            return vector(0,0,0)
0234        return self.direction
0235
0236    def getNormal(self):
0237        """point on line connecting it to the vector normal to the line"""
0238
0239        d=self.getDirection()
0240        return self.p2 - self.p2.dot(d)*d
0241
0242    def homogenous(self):
0243        #not sure why, when or if
0244        cr=p1.cross(p2).norm()
0245        return array((cr[0],cr[1],cr[2],0.))
0246
0247    def homogenous_XY(self):
0248        #not sure why, when or if
0249        tp1=toXY(self.p1)
0250        tp2=toXY(self.p2)
0251        return array(cross(tp1,tp2))
0252
0253    def parameters(self):
0254        """ returns the normal and direction defining the line"""
0255
0256        return self.getNormal(), self.getDirection()
0257
0258
0259class _Plane(Element,Draw.drawPlane):
0260    """ a 2 dimensional surface spanned by two linearly independent vectors
0261
0262inherits  
0263    Element__  , drawPlane__
0264
0265defining instance attributes 
0266    
0267    - _u : the unit normal of the plane
0268    - _d : the distance of the plane from origin
0269    - _s : unit vector perp to unit normal
0270
0271__ class-base.abstracts._element.Element.html
0272__ class-base.drawing.vdraw.drawPlane.html
0273   
0274    """
0275
0276    __opts__= Element.__opts__[:] + ["style","linewidth","scale",
0277                                   "show_normal","normal_width", "grid_scale"]
0278
0279    def __init__(self,*args,**kws):
0280        """intialize attributes, with keywords arguments or defaults"""
0281
0282        Element.__init__(self, *args,**kws)
0283        self.color = kws.get("color",LIGHTGRAY)
0284        self.style = kws.get("style",LINES)
0285        self.linewidth=kws.get("linewidth",.02)
0286        self.scale=kws.get("scale",10)
0287        self.show_normal=kws.get("show_normal",False)
0288        self.normal_width=kws.get("normal_width",.4)
0289        self.grid_scale=kws.get("grid_scale",1)
0290        self._u=Position3(0,0,0)
0291        self._s=Position3(0,0,0)
0292        self._d=0
0293        self.deps=[]
0294
0295    def __repr__(self):
0296        return self.__class__.__name__ +  repr(self._u)#,self.p2,self.p3
0297
0298    def __str__(self):
0299        return self.__class__.__name__  +  repr(self._u)#,self.p2,self.p3
0300
0301    def set_uds_fromPoints(self):
0302        """ set defining attributes from 3 points on the plane"""
0303
0304        t= self.p1.coLinear(self.p2,self.p3)
0305        if t:
0306            print "plane's defining points are colinear"
0307            return False
0308        else:
0309            self._u.set(cross3(self.p1,self.p2,self.p3).norm())
0310            self._d = self._u.dot(self.p1)
0311            self._s.set((self.p1-self.p2).norm())
0312            return True
0313
0314    def set_s_from_u(self,u):
0315        """ set a unit vector perpendicular to the plane's normal vector"""
0316
0317        lxy = hypot(u.x,u.y)
0318        if (lxy >= EPS):
0319            self._s.set(vector(-u.y/lxy,u.x/lxy,0.).norm())
0320        else:
0321            self._s.set(vector(1.,0.,0.))
0322
0323    def rmatrix(self):
0324        """ return a 4x4 matrix representing the plane"""
0325
0326        s=self._s
0327        u=self._u
0328        v=s.cross(u).norm()
0329        normal=u*self._d
0330        return array(((u.x,u.y,u.z,0.),
0331                     (v.x,v.y,v.z,0.),
0332                     (s.x,s.y,s.z,0.),
0333                     (normal.x,normal.y,normal.z,1.)),'d')
0334
0335    def parameters(self):
0336        """return the point on the plane on the vector normal to it,
0337        and 2 unit vectors perpendicular to the normal vector"""
0338
0339        normal=self._u*self._d
0340        t=cross(self._u,self._s)
0341        return normal,self._s,t
0342
0343    def equat(self):
0344        """return the plane equation as a 4 element vector of the
0345        coordinates of the unit normal and the distance from the origin"""
0346
0347        u=self._u
0348        return array([u.x,u.y,u.z,-self._d])
0349
0350    def setshow(self):
0351        """ extend the inherited setshow method for the setting the visiblity of
0352        the normal vector extended to the plane"""
0353
0354        Element.setshow(self)
0355        if self.show_normal:
0356            if self.show and self.Not_null:
0357                self.nrend.visible=True
0358            else:
0359                self.nrend.visible=False
0360
0361
0362class _Triangle(_Plane,Draw.drawTriangle):
0363    """ an extension of the _Plane class providing for the drawing of a triangle
0364    connecting 3 points on or defining a plane
0365
0366inherits  
0367
0368    class `_Plane`__,   drawTriangle__
0369
0370defining instance attributes 
0371    
0372    - p1 : a point of the triangle 
0373    - p2 : a point of the triangle 
0374    - p3 : a point of the triangle 
0375    - _u : the unit normal of the triangle's plane
0376    - _d : the distance of the triangle's plane from the origin
0377    - _s : unit vector perp to normal of the triangle's plane
0378
0379__ class-base.abstracts._real._Plane.html
0380__ class-base.drawing.vdraw.drawTriangle.html
0381    
0382    """
0383
0384    def __init__(self,*args,**kws):
0385        """intialize attributes, with keywords arguments or defaults"""
0386
0387        _Plane.__init__(self, *args,**kws)
0388        self.p1=_Point(append=False)
0389        self.p2=_Point(append=False)
0390        self.p3=_Point(append=False)
0391
0392    def transform(self,mat,obj):
0393        """transform the points defining the triangle by the given matrix"""
0394        self.p1.transform(mat,obj.p1)
0395        self.p2.transform(mat,obj.p2)
0396        self.p3.transform(mat,obj.p3)
0397
0398    def _redraw(self):
0399        """override the _Plane _redraw method"""
0400        Draw.drawTriangle._redraw(self)
0401
0402    def draw(self):
0403        """override the _Plane _draw method"""
0404        Draw.drawTriangle.draw(self)
0405
0406    def _redraw(self):
0407        """override the _Plane _redraw method"""
0408        Draw.drawTriangle._redraw(self)
0409
0410    def povout(self,buf):
0411        """override the _Plane povout method"""
0412        Draw.drawTriangle.povout(self,buf)
0413
0414class _Circle(_Plane,Draw.drawCircle):
0415    """the set of points of a plane that are equidistant from a given point of the plane
0416    
0417inherits  
0418    
0419    Element__ , drawCircle__
0420    
0421defining instance attributes 
0422    
0423    - _center: the circle's center
0424    - _cpoint: a point of the circle's circumference
0425    - _radius: the circle's radius
0426    - _radiusSquared: the square of circle's radius
0427    - _u : the unit normal of the circle's plane
0428    - _d : the distance from origin to the circle's plane
0429    - _s : unit vector perp to normal of the circle's plane
0430
0431__ class-base.abstracts._element.Element.html
0432__ class-base.drawing.vdraw.drawCircle.html
0433    
0434    """
0435
0436    __opts__= _Plane.__opts__[:] + ["precision","fixed"]
0437    __opts__.remove("scale")
0438
0439    def __init__(self,*args,**kws):
0440        """intialize attributes, with keywords arguments or defaults"""
0441
0442        _Plane.__init__(self,*args,**kws)
0443        self.precision = kws.get("precision",40)
0444        self.color = kws.get("color",BLUE)
0445        self.style = kws.get("style",LINES)
0446        self.show_normal=kws.get("show_normal",False)
0447        self.normal_width=kws.get("normal_width",.4)
0448        self.fixed = kws.get("fixed",False)
0449        self.linewidth = kws.get("linewidth",.2)
0450        if self.fixed is True:
0451            self.init=self.findSelf
0452        self._radius=0
0453        self._radiusSquared=0
0454        self._u=Position3(0,0,0)
0455        self._s=Position3(0,0,0)
0456        self._d=0
0457        self._center=_Point(append=False)
0458        self._cpoint=_Point(append=False)
0459        self.type = kws.get("type","Center")
0460        self.deps=[]
0461
0462    def rmatrix(self):
0463        """ return a 4x4 matrix representing the circle's plane and its center"""
0464
0465        s=self._s
0466        u=self._u
0467        v=s.cross(u).norm()
0468        return array(((u.x,u.y,u.z,0.),
0469                     (v.x,v.y,v.z,0.),
0470                     (s.x,s.y,s.z,0.),
0471                     (self._center.x,self._center.y,self._center.z,1.)),'d')
0472
0473    def equat(self):
0474        """return the plane equation as a 4 element vector of the
0475        coordinates of the unit normal and the distance from the origin"""
0476
0477        return array([self._u.x,self._u.y,self._u.z,-self._d])
0478
0479    def set_uds_fromPoints(self):
0480        """ set defining attributes of the circle's plane from 3 points on the plane"""
0481
0482        self._u.set(cross3(self.p1,self.p2,self.p3).norm())
0483        self._d = self._u.dot(self.p1)
0484        self._s.set((self.p1-self.p2).norm())
0485
0486    def set_s_from_u(self,u):
0487        """ set a unit vector perpendicular to the plane's normal vector"""
0488
0489        lxy = hypot(u.x,u.y)
0490        if (lxy >= EPS):
0491            self._s.set(vector(-u.y/lxy,u.x/lxy,0.).norm())
0492        else:
0493            self._s.set(vector(1.,0.,0.))
0494
0495    def transform(self,mat,obj):
0496        """ transform the circle as the transoformation of an array of points on the
0497        circles circumference"""
0498
0499        points=obj.points
0500        rad=PI/(self.precision/2.)
0501        for i,point in enumerate(points):
0502            point.set(self._cpoint)
0503            point.toCircumPoint(self,i*rad)
0504            point.transform(mat,point)
0505        return True
0506
0507    def draw(self):
0508        """override the _Plane _draw method"""
0509        Draw.drawCircle.draw(self)
0510
0511    def _redraw(self):
0512        """override the _Plane _redraw method"""
0513        Draw.drawCircle._redraw(self)
0514
0515    def povout(self,buf):
0516        """override the _Plane povout method"""
0517        Draw.drawCircle.povout(self,buf)
0518
0519class _Sphere(Element,Draw.drawSphere):
0520    """ the set of points in space that are equidistant from a given point
0521
0522inherits  
0523    
0524    Element__ , drawSphere__
0525
0526defining instance attributes 
0527    
0528    - _center  the sphere's center point
0529    - _cpoint  a point on the sphere's circumference
0530    - _radius: the sphere's radius
0531    - _radiusSquared: the square of the sphere's radius
0532
0533__ class-base.abstracts._element.Element.html
0534__ class-base.drawing.vdraw.drawSphere.html
0535    
0536    """
0537
0538    __opts__= Element.__opts__[:] + ["precision","style","linewidth","fixed"]
0539
0540    def __init__(self,*args,**kws):
0541        """intialize attributes, with keywords arguments or defaults"""
0542
0543        Element.__init__(self,*args,**kws)
0544        self.precision= kws.get('precision',10)
0545        self.color = (kws.get("color",GREEN))
0546        self.style=kws.get('style',LINES)
0547        self.linewidth = (kws.get("linewidth",.1))
0548        self.fixed = kws.get("fixed",False)
0549        self._radius=0
0550        self._radiusSquared=0
0551        self._cpoint=_Point(append=False)
0552        self._center=_Point(append=False)
0553        if self.fixed is True:
0554            self.init=self.findSelf
0555        self.deps=[]
0556
0557    def rmatrix(self):
0558        """ return a 4x4 matrix representing the sphers's plane center"""
0559
0560        center=self._center
0561        mat=Element.rmatrix(self)
0562        mat[3:]=array((center.x,center.y,center.z,1.0),'d')
0563        return mat
0564
0565
0566class _PointArray(Element,Draw.drawPointArray):
0567    """an array of points with a defined geometric relationship
0568    
0569inherits
0570    
0571    Element__  , drawPointArray__ 
0572    
0573defining instance attributes 
0574    
0575    points: the positioned points of the array
0576    
0577__ class-base.abstracts._element.Element.html
0578__ class-base.drawing.vdraw.drawPointArray.html
0579    
0580    """
0581
0582    __opts__= Element.__opts__[:] + ["pointsize","density","drawcurve","linewidth","drawpoints","style"]
0583
0584    def __init__(self,*args,**kws):
0585        """intialize attributes, with keywords arguments or defaults"""
0586        self.density=kws.get('density',50)
0587        self.pointsize=kws.get('pointsize',.7)
0588        self.style=kws.get('style',ROUND)
0589        self.drawcurve=kws.get("drawcurve",False)
0590        self.drawpoints=kws.get("drawpoints",True)
0591        if self.drawcurve:
0592            self.linewidth= kws.get("linewidth",.2)
0593        self.points=[]
0594        self.element_array=self.points
0595        Element.__init__(self,*args,**kws)
0596        self.color = kws.get("color",CYAN)
0597        self.deps=[]
0598
0599    def __iter__(self):
0600        """override of Element __iter__ to return the points of the array"""
0601
0602        for point in self.points:
0603            yield point
0604
0605    def __len__(self):
0606        """override of Element __len__ to return the number of points of the array"""
0607
0608        return len(self.points)
0609
0610    def transform(self,mat,obj):
0611        """transform the points of the array by the given 4x4 matrix"""
0612
0613        for point, tpoint in zip(self.points,obj.points):
0614            point.transform(mat,tpoint)
0615
0616    def init(self):
0617
0618        p_append=self.points.append
0619        i=0
0620        while i < self.density:
0621            n=_Point(pointsize=self.pointsize,color=self.
0622                    color,level=self.level,append=False,style=self.style)
0623            if self.drawpoints:
0624                n.init()
0625            p_append(n)
0626            i+=1
0627        Element.init(self)
0628
0629
0630class _LineArray(Element,Draw.drawArray):
0631    """an array of lines with a defined geometric relationship
0632inherits
0633    
0634    Element__ class  drawArray__ 
0635    
0636defining instance attributes 
0637    
0638    lines: the postioned lines of the array
0639
0640__ class-base.abstracts._element.Element.html
0641__ class-base.drawing.vdraw.drawArray.html
0642    
0643    """
0644
0645    __opts__= Element.__opts__[:] + ["linewidth","density","drawradius"]
0646
0647    def __init__(self,*args,**kws):
0648        """intialize attributes, with keywords arguments or defaults"""
0649        self.lines=[]
0650        self.density=kws.get('density',50)
0651        self.linewidth=kws.get('linewidth',.1)
0652        self.drawradius=kws.get('drawradius',5)
0653        self.element_array=self.lines
0654        Element.__init__(self,*args,**kws)
0655        self.color = kws.get("color",MAGENTA)
0656        self.deps=[]
0657
0658    def __iter__(self):
0659        """override of Element __iter__ to return the lines of the array"""
0660
0661        for line in self.lines:
0662             yield line
0663
0664    def __len__(self):
0665        """override of Element __len__ to return the number of lines of the array"""
0666
0667        return len(self.lines)
0668
0669    def transform(self,mat,obj):
0670        """transform the lines of the array by the given 4x4 matrix"""
0671
0672        for line, tline in zip(self.lines,obj.lines):
0673            line.transform(mat,tline)
0674
0675    def init(self):
0676        l_append=self.lines.append
0677        i=0
0678        while i < self.density:
0679            n=_Line(linewidth=self.linewidth,color=self.color,
0680                    level=self.level,append=False)
0681            n.init()
0682            l_append(n)
0683            i+=1
0684        Element.init(self)
0685
0686class _PlaneArray(Element,Draw.drawArray):
0687    """an array of planes with a defined geometric relationship
0688
0689inherits  
0690
0691    Element__ , drawArray__ 
0692
0693defining instance attributes 
0694
0695    planes: the positioned planes of the array
0696
0697__ class-base.abstracts._element.Element.html
0698__ class-base.drawing.vdraw.drawArray.html
0699   
0700    """
0701
0702    __opts__= Element.__opts__[:] + ["linewidth","style","density","scale","draw_density"]
0703
0704    def __init__(self,*args,**kws):
0705        """intialize attributes, with keywords arguments or defaults"""
0706        self.linewidth=kws.get('linewidth',.1)
0707        self.style=kws.get('style',"LINES")
0708        self.density=kws.get('density',25)
0709        self.scale=kws.get('scale',1)
0710        self.grid_scale=kws.get('grid_scale',1)
0711        self.planes=[]
0712        self.element_array=self.planes
0713        Element.__init__(self,*args,**kws)
0714        self.color = kws.get("color",RED)
0715        self.deps=[]
0716
0717    def __iter__(self):
0718        """override of Element __iter__ to return the planes of the array"""
0719
0720        for plane in self.planes:
0721            yield plane
0722
0723    def __len__(self):
0724        """override of Element __len__ to return the number of planes of the array"""
0725
0726        return len(self.planes)
0727
0728    def init(self):
0729        p_append=self.planes.append
0730        i=0
0731        while i < self.density:
0732            n=_Plane(linewidth=self.linewidth,color=self.color,
0733                     level=self.level,scale=self.scale,
0734                     style=self.style,append=False, grid_scale=self.grid_scale)
0735            n.init()
0736            p_append(n)
0737            i+=1
0738        Element.init(self)
0739
0740
0741
0742class _CirclePencil(Element,Draw.drawArray):
0743    """an array of circles with a defined geometric relationship
0744    
0745inherits
0746    
0747    Element__ , drawArray__ 
0748    
0749defining instance attributes 
0750    
0751    circles: the positioned circles of the array
0752
0753__ class-base.abstracts._element.Element.html
0754__ class-base.drawing.vdraw.drawArray.html
0755    
0756    """
0757
0758    __opts__= Element.__opts__[:] + ["linewidth","style","density","precision"]
0759
0760    def __init__(self,*args,**kws):
0761        """intialize attributes, with keywords arguments or defaults"""
0762        self.precision=kws.get("precision",70)
0763        self.linewidth=kws.get("linewidth",.5)
0764        self.style=kws.get("style",LINES)
0765        self.density=kws.get("density",30)
0766        self.circles=[]
0767        Element.__init__(self,*args,**kws)
0768        self.color=kws.get("color",RED)
0769        self.deps=[]
0770
0771    def transform(self,mat,obj):
0772        """transform the circles of the array by the given 4x4 matrix"""
0773
0774        for circle, tarray in zip(self.circles,obj.pointarrays):
0775            circle.transform(mat,tarray)
0776
0777    def __iter__(self):
0778        """override of Element __iter__ to return the circles of the array"""
0779
0780        for circle in self.circles:
0781            yield circle
0782
0783    def __len__(self):
0784        """override of Element __len__ to return the number of circles of the array"""
0785
0786        return len(self.circles)
0787
0788    def init(self):
0789        c_append=self.circles.append
0790        i=0
0791        while i < self.density:
0792            n=_Circle(color=self.color,level=self.level,linewidth=self.linewidth,
0793                   precision=self.precision,style=self.style,append=False)
0794            n.init()
0795            c_append(n)
0796            i+=1
0797        Element.init(self)
0798
0799
0800
0801class _Transformation(Element,Draw.drawArray):
0802    """a mapping of a set of geometric objects
0803    
0804inherits  
0805    
0806    Element__ ,  drawArray__ 
0807
0808defining instance attributes 
0809    
0810    transforms: the transformed positions of the given elements
0811
0812__ class-base.abstracts._element.Element.html
0813__ class-base.drawing.vdraw.drawArray.html
0814    
0815    """
0816
0817    __opts__= Element.__opts__[:] + ["circle_style"]
0818
0819    def __init__(self,*args,**kws):
0820        """intialize attributes, with keywords arguments or defaults"""
0821
0822        Element.__init__(self,*args,**kws)
0823        self.color = kws.get("color",None)
0824        self.level = kws.get("level",None)
0825        self.circle_style = kws.get("circle_style",ROUND)
0826        self.deps=[]
0827
0828    def findSelf(self):
0829        """get the current transformation matrix and apply it to each element's transform method
0830        at each update cycle"""
0831
0832        self._getMat()
0833        for e,t in zip(self.elements,self.transforms):
0834            e.transform(self.mat,t)
0835        return True
0836
0837    def __len__(self):
0838        """override of Element __len__ to return the number of transformed objects """
0839
0840        return len(self.transforms)
0841
0842    def __iter__(self):
0843        """override of Element __iter__ to return the transformed objects """
0844
0845        for transform in self.transforms:
0846            yield transform
0847
0848    def _getMat(self):
0849        """ to be overridden by implementing classes with the matrix defining the
0850        transformation"""
0851
0852        pass
0853    def povout(self,buf):
0854        """ export the objects of the scene's arrays to PovRay SDL"""
0855        for transform in self.transforms:
0856            if hasattr(transform,'points'):
0857                objects=transform.points
0858            else:
0859                objects= transform
0860
0861            print >> buf,"//BEGIN TRANSFORMATION//"
0862            for object in objects:
0863                object.povout(buf)
0864
0865
0866    def init(self):
0867        self.transforms=[]
0868        for e in self.elements:
0869            if self.color:
0870                color=self.color
0871            else:
0872                color=e.color
0873            if self.level:
0874                level=self.level
0875            else:
0876                level=e.level
0877            if isinstance(e,_Point):
0878                n=_Point(pointsize=e.pointsize,color=color,level=level,style=e.style,append=False)
0879                self.transforms.append(n)
0880            elif isinstance(e,_Line):
0881                n=_Line(linewidth=e.linewidth,color=color,level=level,seg=e.seg,append=False)
0882                self.transforms.append(n)
0883            elif isinstance(e,_Circle):
0884                n=_PointArray(linewidth=e.linewidth,color=color,level=level,
0885                             density=e.precision,drawcurve=False,style=self.circle_style,append=False)
0886                self.transforms.append(n)
0887            elif isinstance(e,_PointArray):
0888                n=_PointArray(pointsize=e.pointsize,color=color,level=level,
0889                             drawpoints=e.drawpoints,drawcurve=e.drawcurve,style=e.style,append=False)
0890                self.transforms.append(n)
0891            elif isinstance(e,_Triangle):
0892                n=_Triangle(linewidth=e.linewidth,color=color,level=level,
0893                           style=e.style,append=False)
0894                self.transforms.append(n)
0895        for t in self.transforms:
0896            t.init()
0897        Element.init(self)
0898
0899# module attributes
0900__author__ = "Arthur Siegel <ajsiegel@optonline.com>"
0901__date__ = "Date: 2006-02-02 "
0902__revision__ = "Revision: a1"
0903__url__ = "URL: http://sourceforge.net/projects/pygeo"
0904__copyright__ ="GPL <http://www.opensource.org/licenses/gpl-license.php>"