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"""drawing and graphics related routines to use as mixin classes with objects of real
00233d space"""
0024
0025
0026from pygeo.base.support.pygeoconstants import DIAMOND, FILL, LINES
0027from pygeo.base.analytics.pygeomath import *
0028from pygeoprimitives import *
0029from pygeo.base.analytics._position3 import Position3
0030from pygeo.base.support.pygeoopts import EPS, MAX, TEST_MAX, DO_TESTS
0031
0032def constrain_draw(pos):
0033    """for constraining the drawing position of points where largs values 
0034    relative to the scene scale can cause display prblems.  The option to 
0035    turn off drawing constraints and the 'MAX' constant is by editing the
0036    pygeoopts.py file"""
0037
0038    if TEST_MAX:
0039        try:
0040            m=max(absolute(pos))
0041            if m > MAX:
0042                return (pos/m)*MAX
0043            else:
0044                return pos
0045        except OverflowError:
0046            return (MAX,MAX,MAX)
0047    else:
0048        return pos
0049
0050
0051class drawPoint:
0052    """drawing back-end for objects derived from the _Point class"""
0053
0054    def _redraw(self):
0055        """send current position in scene to render object, and render
0056        in accordance with style sttribute"""
0057        if self.init_draw:
0058            if self.style==DIAMOND:
0059                for r in self.rend:
0060                    r.pos=constrain_draw(self)
0061            else:
0062                self.rend[0].pos =constrain_draw(self)
0063            if self.label:
0064                self.lab.pos= constrain_draw(self)
0065
0066    def setext(self):
0067        """where point is dependent on line and we want to extend the drawing of the 
0068        dependant line to meet the point (needs to be overridden if there is more than on dependent
0069        line
0070        """
0071
0072        for line in self.lines:
0073            if line.seg:
0074                line.get_extension(self)
0075                line._redraw()
0076
0077    def do_trace(self):
0078        """If, on update, traced point has moved within limits defined by
0079        'mintrace' and 'maxtrace' append its new position to the trace
0080        curve"""
0081
0082        from pygeo.base.geometry_real.points.basepoints import Point
0083        delta= self.distance(self.tmparray)
0084        if (self.mintrace < delta < self.maxtrace):
0085            self.rtrace.append(Point(constrain_draw(self),pointsize=self.pointsize,color=self.tracecolor,
0086                                     level=self.level))
0087            self.ntrace.append(pos=constrain_draw(self))
0088        self.tmparray.set(self)
0089
0090    def reset_trace(self):
0091        """Re-intialize list of traced points to None"""
0092
0093        if self.trace:
0094            for r in self.rtrace:
0095                r.show=False
0096                r.setshow()
0097            self.rtrace=[]
0098            self.tmparray.set(self)
0099
0100    def reset_trace_curves(self):
0101        """Re-intialize list of traced curves to None"""
0102
0103        if self.trace:
0104            self.ntrace.pos=[]
0105
0106    def draw(self):
0107        """For consistency in iterating Element's rendering objects, all elements
0108        rendering information is in a list called self.rend. In the case of Points,
0109        it is either a single element list, containing a cvisual sphere object, or a 
0110        2 element list with each element an oriented cvisual pyramid object, which together
0111        form a diamond shape representing the point"""
0112
0113        if self.style==DIAMOND:
0114            self.f=frame()
0115#            self.f.rotate(angle=PI/4.,axis=(1,0,0),pos=(0,0,0))
0116            ps=self.pointsize
0117            self.rend.append(pyramid(frame=self.f,size=(ps,sqrt(2)*ps,sqrt(2)*ps)))
0118            self.rend.append(pyramid(frame=self.f,size=(-ps,sqrt(2)*ps,sqrt(2)*ps)))
0119            for r in self.rend:
0120                r.color=r.initcolor=self.color
0121        else:
0122            self.rend.append(sphere(radius=self.pointsize))
0123            self.rend[0].color=self.rend[0].initcolor=self.color
0124        if self.label:
0125            self.lab=label(box=False, opacity=0.,
0126                         color=self.fontcolor,text=self.label,
0127                         xoffset=self.fontXoffset,yoffset= self.fontYoffset,
0128                         space=.5, height=self.fontsize, border=2)
0129        if self.trace:
0130            self.ntrace = curve(radius=self.tracewidth,
0131                             color=self.tracecolor)
0132        self.init_draw=True
0133
0134    def povout(self,buf):
0135        """ export the scene's points to PovRay SDL"""
0136        print >>buf,"//POINT"
0137        x=self.x
0138        y=self.y
0139        z=self.z
0140        if not self.style==DIAMOND:
0141
0142            print >>buf,"""
0143sphere {
0144 <%f, %f, %f> , %f
0145pigment {
0146 color rgb <%f, %f, %f> filter 0 transmit  0.0 }
0147}
0148"""       %(x,y,z,
0149            self.pointsize,self.color[0],
0150            self.color[1],self.color[2])
0151            if self.trace:
0152                print >>buf,"//POINT TRACE"
0153                for trace in self.rtrace:
0154                    trace.povout(buf)
0155                i=0
0156                while i < len(self.ntrace.pos)-1:
0157                    p1=self.ntrace.pos[i]
0158                    p2=self.ntrace.pos[i+1]
0159                    print >> buf, """
0160cylinder{
0161<%f, %f, %f> , <%f, %f, %f>, %f
0162pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0
0163
0164}"""     %(p1[0],p1[1],p1[2],
0165                 p2[0],p2[1],p2[2],
0166                 self.tracewidth,self.tracecolor[0],
0167                 self.tracecolor[1],self.tracecolor[2])
0168                print >>buf,"""
0169sphere {
0170 <%f, %f, %f> , %f
0171pigment {
0172 color rgb <%f, %f, %f> filter 0 transmit  0.0 }
0173}
0174"""       %(p1[0],p1[1],p1[2],
0175            self.tracewidth,self.tracecolor[0],
0176            self.tracecolor[1],self.tracecolor[2])
0177                i+=1
0178        else:
0179            print >>buf,"""
0180union{
0181    prism {
0182        conic_sweep
0183        linear_spline
0184        0, // height 1
0185        1, // height 2
0186        5, // the number of points making up the shape...
0187        <1,0>,<0,1>,<-1,0>,<0,-1>,<1,0>
0188        translate <0, -1, 0>
0189        pigment { color rgb <%f, %f, %f> filter 0 transmit  0.0}
0190     } 
0191
0192    prism {
0193        conic_sweep
0194        linear_spline
0195        0, // height 1
0196        1, // height 2
0197        5, // the number of points making up the shape...
0198        <1,0>,<0,1>,<-1,0>,<0,-1>,<1,0>
0199        rotate <180, 0, 0>
0200        translate <0, 1, 0>
0201        pigment { color rgb <%f, %f, %f> filter 0 transmit  0.0 }
0202
0203     }   
0204    scale <%f,%f,%f>
0205    translate <%f, %f, %f>
0206
0207}
0208    """    %(color[0],color[1],color[2],color[0],color[1],color[2],
0209               size,size,size,x,y,z)
0210
0211
0212class drawLine:
0213    """drawing back-end for objects derived from the _Line class"""
0214
0215    def _redraw(self):
0216        """send current position of defining points in scene to render object,
0217        and render line or line segment, in accordance with attribute setting"""
0218
0219        if self.seg:
0220            self.rend[0].pos=map(constrain_draw,[self.p1,self.p2])
0221            if self.bounds1:
0222                self.rend[0].append(pos=constrain_draw(self.bounds1))
0223            if self.bounds2:
0224                self.rend[0].append(pos=constrain_draw(self.bounds2))
0225        else:
0226            mid=(self.p1+self.p2)/2.
0227            dir=self.getDirection()
0228            self.f.axis=vector(dir.x,dir.y,dir.z)
0229            self.f.pos=vector(mid.x,mid.y,mid.z)
0230            self.rend[0].pos=self.m  #transpose((self.m, 0*self.m,0*self.m))
0231        if self.show_normal:
0232            norm=self.getNormal()
0233            self.nrend.axis = vector(norm.x,norm.y,norm.z)
0234        if self.extend:
0235            self.setext()
0236        if self.label:
0237            self.setlabel()
0238
0239    def get_extension(self,point):
0240        """ extend the drawing of the line to the given point if it is exterior to
0241        the segment connecting the line's point attributes"""
0242
0243        if self.seg:
0244            if point.show and point.Not_null and self.show and self.Not_null:
0245                a=self.lengthSquared()
0246                b=self.p1.distanceSquared(point)
0247                c=self.p2.distanceSquared(point)
0248                if a > b and a > c:
0249                    return False
0250                elif a < b:
0251                    self.bounds2=point
0252                    self.bounds1=None
0253                    return True
0254                else:
0255                    self.bounds1=point
0256                    self.bounds2=None
0257                    return True
0258            else:
0259                self.bounds1=None
0260                self.bounds2=None
0261                return False
0262        else:
0263            self.bounds1=None
0264            self.bounds2=None
0265            return False
0266
0267    def setlabel(self):
0268        """set position of line's lab, if any"""
0269        labelpos=add(multiply(1-self.lratio,self.p1),
0270                     multiply(self.lratio,self.p2))
0271        self.lab.pos=labelpos
0272
0273
0274    def reset_trace(self):
0275        """Re-intialize list of traced lines to None"""
0276
0277        for r in self.rtrace:
0278            r.show=False
0279            r.setshow()
0280        self.rtrace=[]
0281
0282    def do_trace(self):
0283        from pygeo.base.geometry_real.lines import Line
0284        """If trace set to true, draw new line at current position of points defining the
0285        lines"""
0286
0287        l=Line(Position3(self.p1),Position3(self.p2),
0288               linewidth=self.tracewidth,color=self.tracecolor,
0289               seg=self.seg,level=self.level)
0290        self.rtrace.append(l)
0291
0292    def draw(self):
0293        """for consistency in iterating Element's rendering objects, all elements
0294        rendering information is in a list called self.rend. In the case of Lines,
0295        it is a single element list containing a cvisual curve object"""
0296
0297        self.f=frame()
0298        self.m = array([[MAX,0.,0.],[-MAX,0,0]])
0299        self.rend=[curve(frame=self.f,radius=self.linewidth)]
0300        self.rend[0].color=self.rend[0].inticolor=self.color
0301        if self.label:
0302            self.lab=label(frame=self.f,box=False, opacity=0.,
0303                           color=self.fontcolor,text=self.label,
0304                           xoffset=self.fontXoffset,yoffset= self.fontYoffset,
0305                           space=.5, height=self.fontsize, border=2)
0306        if self.show_normal:
0307            self.nrend=arrow(shaftwidth=self.normal_width,
0308                             color=self.color)
0309        self.init_draw=True
0310
0311    def povout(self,buf):
0312        """ export the scene's lines to PovRay SDL"""
0313
0314        print >> buf, "//LINE"
0315        if self.seg:
0316            i=0
0317            while i < len(self.rend[0].pos)-1:
0318                p1=self.rend[0].pos[i]
0319                p2=self.rend[0].pos[i+1]
0320                if max(absolute(p1-p2)) > EPS:
0321                    print >> buf, """
0322cylinder{
0323<%f, %f, %f> , <%f, %f, %f>, %f
0324pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0
0325
0326}"""     %(p1[0],p1[1],p1[2],
0327                 p2[0],p2[1],p2[2],
0328                 self.linewidth,self.color[0],
0329                 self.color[1],self.color[2])
0330                    print >>buf,"""
0331sphere {
0332 <%f, %f, %f> , %f
0333pigment {
0334 color rgb <%f, %f, %f> filter 0 transmit  0.0 }
0335}
0336"""       %(p1[0],p1[1],p1[2],
0337            self.linewidth,self.color[0],
0338            self.color[1],self.color[2])
0339                i+=1
0340        else:
0341            p1=self.rend[0].pos[0]
0342            p2=self.rend[0].pos[1]
0343            pos=self.f.pos
0344            theta,phi=Position3(self.f.axis).polar()
0345            d_convert=180./PI
0346            theta*=d_convert
0347            phi*=d_convert
0348            rotate = "rotate<%f,%f,%f>" %(0.,90.+theta,phi)
0349            translate="translate<%f,%f,%f>" %(pos.x,pos.y,pos.z)
0350            if max(absolute(p1-p2)) > EPS:
0351                print >> buf, """
0352cylinder{
0353<%f, %f, %f> , <%f, %f, %f>, %f
0354%s
0355%s
0356pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0
0357
0358}"""     %(p1[0],p1[1],p1[2],
0359                 p2[0],p2[1],p2[2],self.linewidth,
0360                 rotate,
0361                 translate,
0362                 self.color[0],self.color[1],self.color[2])
0363        if self.trace:
0364            for trace in self.rtrace:
0365                trace.povout(buf)
0366
0367
0368
0369
0370class drawPlane:
0371    """drawing back-end for objects derived from the _Plane class"""
0372
0373    def _redraw(self):
0374        """send current position of defining plane attributes - the unit normal and distance
0375        from the origin - to the frame encompassing the drawing primtives"""
0376
0377        self.f.axis = self._u
0378        if self._d:
0379            self.f.pos=self._u*self._d
0380        if self.show_normal:
0381            self.nrend.axis = self._u
0382            self.nrend.length= self._d
0383
0384    def draw(self):
0385        """the plane object is represented either by a thin box object or as a mesh of lines - 
0386        taking advantage of the cvisual frame object, assigning the drawing primitives to one
0387        frame, so that further manipulation is of the frame, not the primtives themselves"""
0388
0389        self.f=frame()
0390        self.ext=ext=self.scale*10.
0391        if self.style==FILL:
0392            self.rend.append(box(frame=self.f,length=.01,height=2*ext,width=2*ext,
0393                           color=self.color,alpha=.1,linewidth=self.linewidth))
0394        else:
0395            grid = float(self.grid_scale)
0396            for i in range(int(self.scale*10+1)):
0397                self.rend.append(curve(frame=self.f,pos=[(0,(2*i-ext)/grid,-ext/grid),
0398                                (0,(2*i-ext)/grid,ext/grid)],
0399                                color=self.color,linewidth=self.linewidth))
0400                self.rend.append(curve(frame=self.f,pos=[(0,-ext/grid,(2*i-ext)/grid),
0401                                (0,ext/grid,(2*i-ext)/grid)],
0402                                color=self.color,linewidth=self.linewidth))
0403        if self.show_normal:
0404            self.nrend=arrow(shaftwidth=self.normal_width,
0405                                 color=self.color.alpj)
0406        self.init_draw=True
0407
0408
0409    # can't get satisfied with a plane rendering on Povray for PyGeo's purposes - this will have to do for now
0410    global map_id
0411    map_id =0
0412
0413    def povout(self,buf):
0414        """ export the scene's planes to PovRay SDL"""
0415        print >> buf, "\n //PLANE"
0416
0417        s=self._s
0418        u=self._u
0419        v=s.cross(u).norm()
0420        normal=u*self._d
0421        ext=self.ext
0422        matrix="matrix"
0423        if determinant(self.rmatrix()) > EPS:
0424            matrix=matrix+"<%f,%f,%f,\n" %(u.x,u.y,u.z)
0425            matrix=matrix+" %f,%f,%f,\n" %(v.x,v.y,v.z)
0426            matrix=matrix+" %f,%f,%f,\n" %(s.x,s.y,s.z)
0427            matrix=matrix+" %f,%f,%f>\n" %(normal.x,normal.y,normal.z)
0428        else:
0429            return False
0430
0431        color=self.color
0432
0433        if self.style==FILL:
0434            grid=float(self.grid_scale)
0435            thickness=self.linewidth/10.
0436            box="<%f,%f,%f>\n" %(-ext/grid,-ext/grid,thickness)
0437            box=box+"<%f,%f,%f>\n" %(ext/grid,ext/grid,-thickness)
0438            print >> buf, """
0439box{
0440   %s
0441   rotate <0,90,0>
0442   %s
0443   pigment {color rgb <%f, %f, %f> filter .9 transmit .9
0444 }\n}"""     %(box,matrix,
0445               color[0],color[1],color[2])
0446
0447        else:
0448            grid=float(self.grid_scale)
0449            ext=self.ext
0450            print >>buf , "merge{"
0451            for i in range(int(self.scale*10+1)):
0452                print >>buf , """cylinder{
0453<%f, %f, %f> , <%f, %f, %f>, %f}"""      %(0,(2*i-ext)/grid,-ext/grid,0,(2*i-ext)/grid,
0454                                              ext/grid,self.linewidth)
0455                print >>buf , """cylinder{
0456<%f, %f, %f> , <%f, %f, %f>, %f}"""      %(0,-ext/grid,(2*i-ext)/grid,0,ext/grid,
0457                                             (2*i-ext)/grid,self.linewidth)
0458            print >>buf, """pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0}
0459                         %s}""" %(color[0],color[1],color[2],matrix)
0460
0461class drawTriangle:
0462    """drawing back-end for objects derived from the _Triangle class"""
0463
0464    def _redraw(self):
0465        """send current position of the points defining the triangle to render object, 
0466        and render in accordance with style sttribute"""
0467
0468        if self.style == FILL:
0469            self.rend[0].pos=map(constrain_draw,[self.p1,self.p2,self.p3,self.p3,self.p2,self.p1])
0470            norm1=self._u
0471            norm2=-self._u
0472            self.rend[0].normal=[norm1,norm1,norm1,norm2,norm2,norm2]
0473            self.rend[0].color=self.color
0474        else:
0475            self.rend[0].pos=map(constrain_draw,[self.p1,self.p2,self.p3,self.p1])
0476
0477    def draw(self):
0478        """the triangle object is represented either by a single 'face' - i.e. cvisual triangle mesh -
0479        or as 3 lines"""
0480
0481        if self.style == FILL:
0482            self.rend=[faces()]
0483        else:
0484            self.rend=[curve(radius=self.linewidth)]
0485            self.rend[0].color=self.rend[0].initcolor=self.color
0486        self.init_draw=True
0487
0488    def povout(self,buf):
0489        """ export the scene's triangles to PovRay SDL"""
0490
0491        color=self.color
0492        print >> buf, "//Triangle"
0493        if self.style==FILL:
0494            p1=self.p1
0495            p2=self.p2
0496            p3=self.p3
0497            t1="<%f,%f,%f>" %(p1.x,p1.y,p1.z)
0498            t2="<%f,%f,%f>" %(p2.x,p2.y,p2.z)
0499            t3="<%f,%f,%f>" %(p3.x,p3.y,p3.z)
0500            print >> buf,"""
0501triangle{
0502        %s,
0503        %s
0504        %s
0505        pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0
0506        }
0507}"""     %(t1,t2,t3,color[0],color[1],color[2])
0508
0509        else:
0510            i=0
0511            while i < len(self.rend[0].pos)-1:
0512                p1=self.rend[0].pos[i]
0513                p2=self.rend[0].pos[i+1]
0514                if max(absolute(p1-p2)) > EPS:
0515                    print >> buf, """
0516cylinder{
0517<%f, %f, %f> , <%f, %f, %f>, %f
0518pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0
0519
0520}"""     %(p1[0],p1[1],p1[2],
0521           p2[0],p2[1],p2[2],
0522           self.linewidth,color[0],color[1],color[2])
0523                i+=1
0524
0525###where is povout for triangle??
0526
0527class drawCircle:
0528    """drawing back-end for objects derived from the _Circle class"""
0529
0530    def _redraw(self):
0531        """send current position of the circle's defining attributes - its center,radius, 
0532        plane's unit normal, and plane's distance from origin - to render object, 
0533        and render in accordance with style attribute"""
0534
0535
0536        if self._radius > MAX:
0537            radius= MAX
0538        else:
0539            radius=self._radius
0540        self.f.axis=self._u
0541        self.f.pos=constrain_draw(self._center)
0542        self.rend[0].pos=constrain_draw((self.c*radius))
0543        if self.show_normal:
0544            self.nrend.axis=self._u
0545            self.nrend.length=-self._d
0546
0547    def draw(self):
0548        """the circle object is represented either by a convex polygon or as curve - 
0549        we take advantage of the cvisual frame object, assigning the drawing primitives to one
0550        frame, so that further manipulation is of the frame, not the primtives themselves"""
0551
0552        self.f = frame()
0553        div=2*PI/self.precision
0554        t = arrayrange(div,2*PI+div*2,div)
0555        self.c = transpose( (0*t, sin(t), cos(t)) )
0556        if self.style==FILL:
0557            self.rend=[convex(frame=self.f,color=self.color)]
0558        else:
0559            self.rend=[curve(frame=self.f,color=self.color,
0560                             radius=self.linewidth)]
0561        if self.show_normal:
0562            self.nrend=arrow(pos=(0,0,0),shaftwidth=self.normal_width,
0563                            color=self.color)
0564        self.init_draw=True
0565
0566    def povout(self,buf):
0567        """ export the scene's triangles to PovRay SDL"""
0568
0569        print >> buf, "//CIRCLE"
0570        center=self._center
0571        s=self._s
0572        radius=self._radius
0573        u=self._u
0574        v= s.cross(u).norm()
0575        matrix="matrix"
0576        matrix=matrix+"<%f,%f,%f," %(u.x,u.y,u.z)
0577        matrix=matrix+" %f,%f,%f," %(v.x,v.y,v.z)
0578        matrix=matrix+" %f,%f,%f," %(s.x,s.y,s.z)
0579        matrix=matrix+" %f,%f,%f>" %(center.x,center.y,center.z)
0580        if self.style==LINES:
0581            print >> buf,"""
0582torus {
0583    %f, %f
0584    rotate <0,0,-90>
0585    %s
0586    pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0
0587}
0588}"""   %(radius,self.linewidth,matrix,
0589            self.color[0],self.color[1],self.color[2])
0590        else:
0591            poly=" "
0592            for pos in self.rend[0].pos:
0593              poly = poly + "<%f,%f,%f>" %(pos[0],pos[1],pos[2])
0594            print >> buf,"""
0595polygon{
0596   %i,
0597   %s
0598   %s
0599   pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0
0600 }
0601}"""     %(len(self.rend[0].pos),poly,matrix,
0602               self.color[0],self.color[1],self.color[2])
0603
0604class drawSphere:
0605    """drawing back-end for objects derived from the _Sphere class"""
0606
0607    def _redraw(self):
0608        """send current position of the sphjere's defining attributes - its radius 
0609        and center - to render object, and render in accordance with style sttribute"""
0610
0611        radius=self._radius
0612        center=constrain_draw(self._center)
0613        if radius > MAX:
0614            radius= MAX
0615        if self.style == FILL:
0616            self.rend[0].pos=center
0617            self.rend[0].radius=radius
0618        else:
0619            self.f.pos=center
0620            j=0
0621            k=self.precision
0622            while j < self.precision:
0623                self.rend[j].pos= self.stacks[j] * radius
0624                self.rend[k].pos=self.slices[j] * radius
0625                j+=1
0626                k+=1
0627
0628    def draw(self):
0629        """the sphere object is represented either by a cvisual sphere or as a wire mesh
0630        of cvisual curves"""
0631
0632        self.f=frame()
0633        if self.style == FILL:
0634            self.rend.append(sphere(frame=self.f))
0635            self.rend[0].color=self.rend[0].initcolor=self.color
0636        else:
0637            ws=wiresphere(self.precision)
0638            self.stacks=ws.getstacks()
0639            self.slices=ws.getslices()
0640            self.f=frame()
0641            j=0
0642            while j < self.precision*2:
0643                self.rend.append(curve(frame=self.f,color=self.color,
0644                                radius=self.linewidth))
0645                j+=1
0646        self.init_draw=True
0647
0648    def povout(self,buf):
0649        """ export the scene's spheres to PovRay SDL"""
0650
0651        center=self._center
0652        if self.style==FILL:
0653            print >> buf,"//SPHERE"
0654            print >> buf,"""
0655sphere{
0656 <%f, %f, %f> , %f
0657 pigment {
0658 color rgb <%f, %f, %f> filter 0 transmit  0.0
0659 }
0660}
0661"""     %(center.x,center.y,center.z,
0662          self._radius,self.color[0],
0663          self.color[1],self.color[2])
0664        elif self.style == LINES:
0665            for rend in self.rend:
0666                i=0
0667                while i < len(rend.pos)-1:
0668                    p1=rend.pos[i]
0669                    p2=rend.pos[i+1]
0670                    print >> buf, """
0671cylinder{
0672<%f, %f, %f> , <%f, %f, %f>, %f
0673translate <%f, %f, %f>
0674pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0
0675
0676}"""     %(p1[0],p1[1],p1[2],
0677                 p2[0],p2[1],p2[2],
0678                 self.linewidth,
0679                 center.x,center.y,center.z,
0680                 self.color[0],
0681                 self.color[1],self.color[2])
0682                    print >>buf,"""
0683sphere {
0684 <%f, %f, %f> , %f
0685translate <%f, %f, %f>
0686pigment {
0687 color rgb <%f, %f, %f> filter 0 transmit  0.0 }
0688}
0689"""       %(p1[0],p1[1],p1[2],
0690            self.linewidth,
0691            center.x,center.y,center.z,
0692            self.color[0],self.color[1],self.color[2])
0693                    i+=1
0694
0695class drawArray:
0696    """generalized drawing back-end for array objects, i.e. _LineArray, _CirclePencil ,etc. """
0697
0698    def _redraw(self):
0699        """iterate through the objects of the array and call the objects _redraw routine to redraw
0700        at its current position"""
0701
0702        for object in self:
0703            object._redraw()
0704
0705    def draw(self):
0706        """the objects of the array get initialized on creation by the array's init method - this is only
0707        to mark the array itself as initialized """
0708
0709        self.init_draw=True
0710
0711    def povout(self,buf):
0712        """ export the objects of the scene's arrays to PovRay SDL"""
0713
0714        print >> buf,"//BEGIN ARRAY//"
0715        for object in self:
0716            object.povout(buf)
0717
0718class drawPointArray(drawArray):
0719    """override the generalized array drawing back-end for _PointArrays, which
0720    can draw the curves connecting the arrays points, as well as the points themselves"""
0721
0722    def _redraw(self):
0723        """after redrawing the points, if the _PointArray's drawcruve attribute 
0724        is set to True, send current positions of points to the cvisual curve object"""
0725
0726        drawArray._redraw(self)
0727        if self.drawcurve:
0728            self.crend[0].pos=map(constrain_draw,[point for point in self.points])
0729    def draw(self):
0730        """the points of the array have been initialized on creation in the _PointArray init method -
0731        here we intialize a curve to be traced by the array if that drawcurve attribute is True"""
0732
0733        if self.drawcurve:
0734            self.crend=[curve(radius=self.linewidth)]
0735            self.crend[0].color=self.initcolor=self.color
0736        drawArray.draw(self)
0737
0738    def povout(self,buf):
0739        """ export the scene's pointarrays to PovRay SDL and, if the drawcurve attribute is set to
0740        true, the curve etched by the loci of the array of points"""
0741
0742        if self.drawpoints:
0743            drawArray.povout(self,buf)
0744        if self.drawcurve:
0745            print >> buf,"//CURVE LINES"
0746            rend=self.crend[0]
0747            i=0
0748            while i < len(rend.pos)-1:
0749                p1=rend.pos[i]
0750                p2=rend.pos[i+1]
0751                if max(absolute(p1-p2)) > EPS:
0752                    print >> buf, """
0753cylinder{
0754<%f, %f, %f> , <%f, %f, %f>, %f
0755pigment {color rgb <%f, %f, %f> filter 0 transmit  0.0
0756
0757}
0758"""         %(p1[0],p1[1],p1[2],
0759            p2[0],p2[1],p2[2],
0760            self.linewidth,
0761            self.color[0],
0762            self.color[1],self.color[2])
0763                    print >>buf,"""
0764sphere {
0765 <%f, %f, %f> , %f
0766pigment {
0767 color rgb <%f, %f, %f> filter 0 transmit  0.0 }
0768}
0769"""        %(p1[0],p1[1],p1[2],
0770             self.linewidth,
0771             self.color[0],self.color[1],self.color[2])
0772                i+=1
0773
0774
0775# module attributes
0776__author__ = "Arthur Siegel <ajsiegel@optonline.com>"
0777__date__ = "Date: 2006-02-02 "
0778__revision__ = "Revision: a1"
0779__url__ = "URL: http://source.net/projects/pygeo"
0780__copyright__ ="GPL <http://www.opensource.org/licenses/gpl-license.php>"