예제 #1
0
class Meter(Group):
    """
    A meter object as in Mike'n'Ike
     
    """
    height = .7
    width = 1.8 * height

    angle = 45
    bg = Color(1)
    mcolor = Color(.8)

    def __init__(self, **args):
        Group.__init__(self, **args)

        h = self.height
        w = self.width

        self.append(Rectangle(width=1.8 * h, height=h, bg=self.bg))

        p = Path(P(.1, .1),
                 C(0, 0),
                 P(w - .1, .1),
                 P(w - .2, .1),
                 C(0, 0),
                 P(.2, .1),
                 closed=1,
                 bg=self.mcolor,
                 fg=None)

        self.append(
            p,
            Path(P(w / 2., .1), U(self.angle, h * .9)),
        )
예제 #2
0
def CZGate(c=P(0, 0), controlDist=1.0, direction="up", side=0.5):
    """
    Controlled Z gate

    @param controlDist: distance to the control
    @type controlDist: float

    @param direction: in which direction is the control?  up/down
    @type direction: string

    @param side: length of the box side
    @type side: float
    """
    if direction is "up":
        return Group(
            Circle(c=c + P(0, controlDist), r=0.065, bg=Color("black")),
            Path(c + P(0, side / 2.), c + P(0, controlDist)),
            Rectangle(width=side, height=side, c=c, bg=Color("white")),
            TeX(r'Z', c=c))
    elif direction is "down":
        return Group(
            Circle(c=c - P(0, controlDist), r=0.65, bg=Color("black")),
            Path(c - P(0, side / 2.), c - P(0, controlDist)),
            Rectangle(width=side, height=side, c=c, bg=Color("white")),
            TeX(r'Z', c=c))
예제 #3
0
class Circled(Group, Circle):
    '''
    Draws a circle around an object,

    @cvar pad: padding around object
    @cvar r: overide the radius of the circle
    
    '''

    fg = Color(0)
    bg = Color(1)
    pad = 0.1

    def __init__(self, obj, **options):

        Circle.__init__(self, **options)
        Group.__init__(self, **options)

        bbox = obj.bbox()

        w = bbox.width + 2 * self.pad
        h = bbox.height + 2 * self.pad

        self.r = options.get('r', max(w, h) / 2.)

        self.append(
            Circle(r=self.r,
                   bg=self.bg,
                   fg=self.fg,
                   c=obj.c,
                   linewidth=self.linewidth,
                   dash=self.dash),
            obj,
        )
예제 #4
0
    def __init__(self, **options):
        # initialise the base class
        Group.__init__(self, **options)

        self.height = 2.0
        self.width = 3.0
        self.angle = 0.0
        self.pinLength = 0.5
        self.fg = Color(0)
        self.bg = Color(1)
예제 #5
0
class LambdaPlate(Group):
    """
    Lambda plate; shifts optical signal by a half or quarter wavelength
    
    @ivar height: height of the lambda plate
    @type height: float

    @ivar width: width of the lambda plate
    @type width: float

    @ivar angle: rotation angle
    @type angle: float

    @ivar fg: foreground colour
    @type fg: L{Color} object

    @ivar bg: background colour
    @type bg: L{Color} object
    """

    height = 1.0
    width = 0.3
    angle = 0.0
    fg = Color(0)
    bg = Color(1)

    def __init__(self, **options):
        # inherit from the base class
        Group.__init__(self, **options)

        # process the options if any
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)
        self.height = options.get("height", self.height)
        self.width = options.get("width", self.width)
        self.angle = options.get("angle", self.angle)

        # make the beam splitter
        lp = Group()
        lp.append(
            Path(P(0, 0),
                 P(-self.width, 0),
                 P(-self.width, self.height),
                 P(0, self.height),
                 P(0, 0),
                 P(-self.width, self.height),
                 fg=self.fg,
                 bg=self.bg))

        # rotate if necessary
        lp.rotate(self.angle, p=lp.bbox().c)

        self.append(lp)
예제 #6
0
class FreeSpace(Group):
    """
    A patch of free space (for example, in an interferometer)

    @ivar height: height of free space box
    @type height: float

    @ivar width: width of free space box (some might say "length")
    @type width: float

    @ivar angle: rotation angle
    @type angle: float

    @ivar fg: foreground colour
    @type fg: L{Color} object

    @ivar bg: background colour
    @type bg: L{Color} object
    """

    height = 1.0
    width = 3.0
    angle = 0.0
    fg = Color(0)
    bg = Color(1)

    def __init__(self, **options):
        # inherit from the base class
        Group.__init__(self, **options)

        # process the options if any
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)
        self.height = options.get("height", self.height)
        self.width = options.get("width", self.width)
        self.angle = options.get("angle", self.angle)

        # make the free space
        fs = Group()
        fs.append(
            Path(P(0, 0),
                 P(0, self.height),
                 P(self.width, self.height),
                 P(self.width, 0),
                 closed=1,
                 fg=self.fg,
                 bg=self.bg,
                 dash=Dash()))

        # rotate if necessary
        fs.rotate(self.angle, p=fs.bbox().c)

        self.append(fs)
예제 #7
0
class Laser(Group):
    """
    Laser

    @ivar height: laser box height
    @type height: float

    @ivar width: laser box width (some might say "length")
    @type width: float

    @ivar angle: rotation angle
    @type angle: float

    @ivar fg: foreground colour
    @type fg: L{Color} object

    @ivar bg: background colour
    @type bg: L{Color} object
    """

    height = 1.0
    width = 3.0
    angle = 0.0
    fg = Color(0)
    bg = Color(1)

    def __init__(self, **options):
        # inherit from the base class
        Group.__init__(self, **options)

        # process the options if any
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)
        self.height = options.get("height", self.height)
        self.width = options.get("width", self.width)
        self.angle = options.get("angle", self.angle)

        # make the laser
        laser = Group()
        laser.append(
            Path(P(0, 0),
                 P(0, self.height),
                 P(self.width, self.height),
                 P(self.width, 0),
                 closed=1,
                 fg=self.fg,
                 bg=self.bg))

        # rotate if necessary
        laser.rotate(self.angle, p=laser.bbox().c)

        self.append(laser)
예제 #8
0
class PhaseShifter(Group):
    """
    Phase shifter

    @ivar width: phase shifter width
    @type width: float

    @ivar height: phase shifter height
    @type height: float

    @ivar angle: angle through which to rotate the phase shifter
    @type angle: float

    @ivar fg: foreground colour
    @type fg: L{Color} object

    @ivar bg: background colour
    @type bg: L{Color} object
    """

    width = 0.5
    height = 0.7
    angle = 0
    fg = Color(0)
    bg = Color(1)

    def __init__(self, **options):
        # inherit from base class
        Group.__init__(self, **options)

        # process the options if any
        self.width = options.get("width", self.width)
        self.height = options.get("height", self.height)
        self.angle = options.get("angle", self.angle)
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)

        # now make the phase shifter
        ps = Path(
            P(0, 0),
            P(self.width / 2.0, self.height),
            P(self.width, 0),
            closed=1,
            fg=self.fg,
            bg=self.bg,
        )

        # rotate if necessary
        if self.angle != 0:
            ps.rotate(self.angle, p=ps.bbox().c)

        self.append(ps)
예제 #9
0
class BSLine(Group):
    """
    Beam splitter as a line (i.e. a half-slivered mirror)

    @ivar height: height of the beam splitter
    @type height: float

    @ivar thickness: thickness of the beam splitter
    @type thickness: float

    @ivar angle: rotation angle
    @type angle: float

    @ivar fg: foreground colour
    @type fg: L{Color} object

    @ivar bg: background colour
    @type bg: L{Color} object
    """

    height = 1.0
    thickness = 0.2
    angle = 45.0
    fg = Color(0)
    bg = Color(1)

    def __init__(self, **options):
        # inherit from the base class
        Group.__init__(self, **options)

        # process the options if any
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)
        self.height = options.get("height", self.height)
        self.thickness = options.get("thickness", self.thickness)
        self.angle = options.get("angle", self.angle)

        # make the beam splitter
        bs = Group()
        bs.append(
            Path(P(0, 0),
                 P(0, self.height),
                 P(self.thickness, self.height),
                 P(self.thickness, 0),
                 closed=1,
                 fg=self.fg,
                 bg=self.bg))

        # rotate if necessary
        bs.rotate(self.angle, p=bs.bbox().c)

        self.append(bs)
예제 #10
0
def classicalpath(*paths):
    '''
    @return: classical path
    @param paths: 1 or more Path() objects
    '''
    g = Group()

    for path in paths:
        g.append(path.copy(linewidth=2, fg=Color(0)))

    # reuse these paths
    for path in paths:
        g.append(path(linewidth=1, fg=Color(1)))

    return g
예제 #11
0
class BSBox(Group):
    """
    Beam splitter as a box as opposed to a line

    @ivar height: height of the beam splitter (equal to its width)
    @type height: C{float}

    @ivar angle: rotation angle
    @type angle: C{float}

    @ivar fg: foreground colour
    @type fg: L{Color} object

    @ivar bg: background colour
    @type bg: L{Color} object
    """

    height = 1.0
    angle = 0.0  # not going to be used much (maybe for a Ralph-splitter ;-))
    fg = Color(0)
    bg = Color(1)

    def __init__(self, **options):
        # inherit from the base class
        Group.__init__(self, **options)

        # process the options if any
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)
        self.height = options.get("height", self.height)
        self.angle = options.get("angle", self.angle)

        # make the beam splitter
        bs = Group()
        bs.append(
            Path(P(0, 0),
                 P(0, self.height),
                 P(self.height, self.height),
                 P(self.height, 0),
                 P(0, 0),
                 P(self.height, self.height),
                 fg=self.fg,
                 bg=self.bg))

        # rotate if necessary
        bs.rotate(self.angle, p=bs.bbox().c)

        self.append(bs)
예제 #12
0
class Detector(Group):
    '''
    A D shaped detector, can be given an object to surround
    '''

    height = .8
    width = height / 2.
    bg = Color(1)
    fg = Color(0)
    pad = .1

    def __init__(self, object=None, **options):
        if object is not None:
            # use the object's boundingbox when width and height not supplied
            bb = object.bbox()
            w = bb.width + 2 * self.pad
            h = bb.height + 2 * self.pad

            self.width = options.get("width", max(w, self.width))
            self.height = options.get("height", max(h, self.height))
        Group.__init__(self, **options)

        if self.width > self.height:
            p = Path(P(0, 0),
                     P(0, self.height),
                     P(self.width - self.height / 2., self.height),
                     C(90, 0),
                     P(self.width, self.height / 2.),
                     C(180, 90),
                     P(self.width - self.height / 2., 0),
                     closed=1)
        else:

            p = Path(P(0, 0),
                     P(0, self.height),
                     C(90, 0),
                     P(self.width, self.height / 2.),
                     C(180, 90),
                     closed=1)

        p(bg=options.get("bg", self.bg), fg=options.get("fg", self.fg))

        self.append(p)
        if object is not None:
            # object looks better if it's slightly off centre
            # since one side is curved. pad/3 is about right
            object.c = P(self.width / 2. - self.pad / 3., self.height / 2.)
            self.append(object)
예제 #13
0
def BS(sw=P(0, 0), label=None, h=1.0):
    """
    Beam splitter; displayed as a line possibly more useful in linear optics
    quantum computation diagrams

    @param sw: location of the south-west corner of the object
    @type sw: L{P} object

    @param label: beam splitter label
    @type label: string

    @param h: beam splitter height
    @type h: float
    """
    buff = P(0, 0.1)
    b = Path(sw - buff,
             sw + P(0, h) + buff,
             sw + P(h, h) + buff,
             sw + P(h, 0) - buff,
             sw - buff,
             fg=None,
             bg=Color("white"))
    p1 = Path(sw, sw + P(h, h))
    p2 = Path(sw + P(0, h), sw + P(h, 0))
    p3 = Path(sw + P(h / 4, h / 2),
              sw + P(h, 0) + P(-h / 4, h / 2),
              linewidth=1)

    if label is not None:
        label['w'] = sw + P(h, 0) + P(-h / 4, h / 2)
        return Group(b, p1, p2, p3, label)
    else:
        return Group(b, p1, p2, p3)
예제 #14
0
    def __init__(self, **options):
        # intitialise base class
        Group.__init__(self, **options)

        self.sep = 0.25
        self.width = 1.0
        self.angle = 0.0
        self.pinLength = 0.5
        self.fg = Color(0)
        self.bg = Color(1)

        # process the options if any
        self.sep = options.get("sep", self.sep)
        self.width = options.get("width", self.width)
        self.angle = options.get("angle", self.angle)
        self.pinLength = options.get("pinLength", self.pinLength)
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)

        pinIn = Group(
                Path( 
                    P(0, 0), 
                    P(self.pinLength, 0),
                    )
                )
        cap = Group( 
                Path(pinIn.e+P(0, -self.width/2.0), 
                    pinIn.e+P(0, self.width/2.0)), 
                Path(pinIn.e+P(self.sep, -self.width/2.0), 
                    pinIn.e+P(self.sep, self.width/2.0)),
                )
        pinOut = Path(
                cap.e, 
                cap.e+P(self.pinLength, 0))

        # group the objects together
        obj = Group(pinIn, pinOut, cap)

        # apply the colours
        obj.apply(fg=self.fg, bg=self.bg)

        # rotate if necessary
        if self.angle != 0.0:
            obj.rotate(self.angle, p=obj.c)

        # set the object to myself
        self.append(obj)
예제 #15
0
class Box(Group, Rectangle):
    '''
    Draws a box around an object,
    the box can be placed acording to standard Area tags

    @cvar pad: padding around object
    @cvar width: overide the width of the box
    @cvar height: override the height of the box
    '''

    # set these preferences different from Rectangle:
    fg = Color(0)
    bg = Color(1)
    pad = .2

    width = None
    height = None

    def __init__(self, obj, **options):
        Rectangle.__init__(self, **options)
        Group.__init__(self, **options)

        bbox = obj.bbox()

        self.object = obj

        w = bbox.width + 2 * self.pad
        h = bbox.height + 2 * self.pad

        # overide the width and height if supplied
        if self.width is None:
            self.width = options.get('width', w)
        if self.height is None:
            self.height = options.get('height', h)

        self.append(
            Rectangle(width=self.width,
                      height=self.height,
                      bg=self.bg,
                      fg=self.fg,
                      c=obj.c,
                      r=self.r,
                      linewidth=self.linewidth,
                      dash=self.dash),
            obj,
        )
예제 #16
0
def Cnot(c=P(0, 0), targetDist=1.0, direction="up"):
    """
    Controlled NOT gate

    @param targetDist: distance to the target rail
    @type targetDist: float

    @param direction: in which direction is the target rail?  up/down
    @type direction: string
    """
    if direction is "up":
        return Group(Circle(r=0.06, bg=Color("black"), c=c),
                     Circle(r=0.2, c=c + P(0, targetDist)),
                     Path(c, c + P(0, targetDist + 0.2)))
    elif direction is "down":
        return Group(Circle(r=0.06, bg=Color("black"), c=c),
                     Circle(r=0.2, c=c + P(0, -targetDist)),
                     Path(c, c + P(0, -targetDist - 0.2)))
예제 #17
0
def ZGate(c=P(0, 0), side=0.5):
    """
    Z gate

    @param side: length of the box side
    @type side: float
    """
    return Group(Rectangle(width=side, height=side, c=c, bg=Color("white")),
                 TeX(r'Z', c=c))
예제 #18
0
class Boxed(Group, Rectangle):
    '''
    Draws a box around an object,
    the box can be placed acording to standard Area tags

    @cvar pad: padding around object
    @type pad: float

    @cvar width: overide the width of the box
    @type width: float

    @cvar height: override the height of the box
    @type height: float
    '''

    fg = Color(0)
    bg = Color(1)
    pad = 0.2

    def __init__(self, obj, **options):

        Rectangle.__init__(self, **options)
        Group.__init__(self, **options)

        bbox = obj.bbox()

        w = bbox.width + 2 * self.pad
        h = bbox.height + 2 * self.pad

        self.width = options.get('width', w)
        self.height = options.get('height', h)

        self.append(
            Rectangle(width=self.width,
                      height=self.height,
                      bg=self.bg,
                      fg=self.fg,
                      c=obj.c,
                      r=self.r,
                      linewidth=self.linewidth,
                      dash=self.dash),
            obj,
        )
예제 #19
0
    def __init__(self, **options):
        # intitialise base class
        Group.__init__(self, **options)

        self.length = 3.0
        self.width = 1.0
        self.angle = 0.0
        self.pinLength = 0.5
        self.fg = Color(0)
        self.bg = Color(1)

        # process the options if any
        self.length = options.get("length", self.length)
        self.width = options.get("width", self.width)
        self.angle = options.get("angle", self.angle)
        self.pinLength = options.get("pinLength", self.pinLength)
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)

        pinIn = Group(
                Path( 
                    P(0, 0), 
                    P(self.pinLength, 0)
                    )
                )
        resistor = Rectangle(w=pinIn.e, width=self.length, height=self.width)
        pinOut = Path(
                resistor.e, 
                resistor.e+P(self.pinLength, 0))

        # collect the objects together
        obj = Group(pinIn, pinOut, resistor)

        # apply the colours
        obj.apply(fg=self.fg, bg=self.bg)

        # rotate if necessary
        if self.angle != 0.0:
            obj.rotate(self.angle, p=obj.c)

        # return object to myself
        self.append(obj)
예제 #20
0
class Poster(Page, VAlign):
    '''
    A poster class  

    @cvar size: the size of the poster eg A0
    @cvar orientation: portrait or landscape
    @cvar space: space between vertically aligned objects appended to poster
    @cvar topspace: initial space at top of poster
    @cvar bg: background color of poster (unless background() method 
    is overiden)
    '''

    size = "A0"
    orientation = "portrait"

    bg = Color('DarkSlateBlue')

    space = 1

    topspace = 2

    def __init__(self, *objects, **options):
        Page.__init__(self, **options)
        VAlign.__init__(self, **options)

        back = self.background()

        # use Page's append so background doesn't get aligned
        Page.append(self, back)

        # add invisible area at top to start alignment
        a = Area(width=0, height=self.topspace - self.space, n=self.area().n)
        self.append(a)

    def background(self):
        '''
        Return background for poster
        '''
        area = self.area()

        signature = Text(
            'Created with PyScript.  http://pyscript.sourceforge.net',
            size=14,
            fg=Color(1))

        signature.se = area.se + P(-.5, .5)
        return Group(
            Rectangle(width=area.width,
                      height=area.height,
                      fg=None,
                      bg=self.bg),
            signature,
        )
예제 #21
0
    def background(self):
        '''
        Return background for poster
        '''
        area = self.area()

        signature = Text(
            'Created with PyScript.  http://pyscript.sourceforge.net',
            size=14,
            fg=Color(1))

        signature.se = area.se + P(-.5, .5)
        return Group(
            Rectangle(width=area.width,
                      height=area.height,
                      fg=None,
                      bg=self.bg),
            signature,
        )
예제 #22
0
class TeXArea(Group):
    '''
    Typeset some LaTeX within a fixed width minipage environment.

    @cvar width: the width of the environment
    @type width: float

    @cvar iscale: initial scale of the tex
    @type iscale: float

    @cvar align: alignment of the LaTeX to box if it iss smaller than 
    the full width
    @type align: string (anchor point)

    @cvar fg: color of TeX
    @type fg: L{Color} object
    '''

    # has to be different from groups width attribute
    width = 9.4
    iscale = 1
    fg = Color(0)
    align = "w"

    def __init__(self, text, **options):
        Group.__init__(self, **options)

        # set up tex width ... this relies on latex notion of
        # a point being accurate ... adjust for tex_scale too
        width_pp = int(self.width / float(self.iscale) * defaults.units)

        t = TeX(r'\begin{minipage}{%dpt}%s\end{minipage}' % (width_pp, text),
                fg=self.fg,
                iscale=self.iscale)

        # use this for alignment as the latex bounding box may be smaller
        # than the full width
        a = Area(width=self.width, height=0)

        Align(t, a, a1=self.align, a2=self.align, space=0)

        self.append(a, t)
예제 #23
0
def detector(**options):
    '''
    @return: a D shaped detector
    '''
    r = 0.3
    c = 0.65 * r
    path = [
        P(0, -r),
        P(0, r),
        C(P(c, r), P(r, c)),
        P(r, 0),
        C(P(r, -c), P(c, -r)),
        P(0, -r)
    ]
    options['bg'] = options.get('bg', Color(.8))
    options['closed'] = 1
    p = apply(Path, path, options)
    a = Area(width=r, height=2 * r, e=P(0, 0))

    return Group(a, p)
예제 #24
0
class QWire(NoWire):
    """
    Class representing a quantum wire
    """

    fg = Color(0)
    linewidth = None
    dash = None

    def set(self, y, e, w):
        """
        Set the east, west and y postions of the QWire
        """
        path = Path(P(w, y),
                    P(e, y),
                    fg=self.fg,
                    linewidth=self.linewidth,
                    dash=self.dash)
        self.append(path)
        return self
예제 #25
0
def cbox(obj, x, yt, yc):
    '''
    @param obj: the object to put a box around
    @type obj: object

    @param x: x position of line and centre of box
    @type x: float

    @param yt: y position of target
    @type yt: float

    @param yc: y position of control
    @type yc: float

    @return: a controlled box
    '''
    g = Group(
        Path(P(x, yt), P(x, yc)),
        Boxed(obj, c=P(x, yt), bg=Color(1)),
        Dot(P(x, yc)),
    )
    return g
예제 #26
0
    def __init__(self, obj, **options):
        bbox = obj.bbox()

        pad = .1
        r = max(bbox.width + 2 * pad, bbox.height + 2 * pad) / 2.0

        self.width = 2.0 * r
        self.height = 2.0 * r

        self.bg = options.get('bg', Color(1))
        if options.has_key('bg'):
            del options['bg']

        apply(Group.__init__, (self, ), options)
        apply(Area.__init__, (self, ), options)

        obj.c = P(r, r)

        self.append(
            Circle(r=r, bg=self.bg, c=P(r, r)),
            obj,
        )
예제 #27
0
    def __init__(self, obj, **options):
        bbox = obj.bbox()

        pad = .1
        w = bbox.width + 2 * pad
        h = bbox.height + 2 * pad

        self.width = w
        self.height = h
        self.bg = options.get('bg', Color(1))
        if options.has_key('bg'):
            del options['bg']

        apply(Group.__init__, (self, ), options)
        apply(Area.__init__, (self, ), options)

        obj.c = P(w / 2., h / 2.)

        self.append(
            Rectangle(width=w, height=h, bg=self.bg),
            obj,
        )
예제 #28
0
class Detector(Group):
    """
    A D-shaped detector

    @cvar height: detector height
    @type height: float

    @cvar width: detector width
    @type width: float

    @ivar fg: foreground colour
    @type fg: L{Color} object

    @ivar bg: background colour
    @type bg: L{Color} object

    @cvar pad: space padding around object
    @type pad: float

    @ivar angle: rotation angle
    @type angle: float
    """

    height = 0.8
    width = height / 2.0
    bg = Color(1)
    fg = Color(0)
    pad = 0.1
    angle = 0.0

    def __init__(self, **options):
        Group.__init__(self, **options)
        p = Group()

        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)
        if self.width > self.height:
            p.append(
                Path(P(0, 0),
                     P(0, self.height),
                     P(self.width - self.height / 2.0, self.height),
                     C(90, 0),
                     P(self.width, self.height / 2.0),
                     C(180, 90),
                     P(self.width - self.height / 2.0, 0),
                     fg=self.fg,
                     bg=self.bg,
                     closed=1))
        else:
            p.append(
                Path(P(0, 0),
                     P(0, self.height),
                     C(90, 0),
                     P(self.width, self.height / 2.0),
                     C(180, 90),
                     closed=1))

        # rotate if necessary
        self.angle = options.get("angle", self.angle)
        p.rotate(self.angle, p=p.bbox().c)

        self.append(p)
예제 #29
0
class Modulator(Group):
    """
    Modulator (EOM, AOM etc.)

    @ivar height: modulator box height
    @type height: float

    @ivar width: modulator box width
    @type width: float

    @ivar angle: rotation angle
    @type angle: float

    @ivar fg: foreground colour
    @type fg: L{Color} object

    @ivar bg: background colour
    @type bg: L{Color} object
    """

    height = 0.5
    width = 1.0
    angle = 0.0
    fg = Color(0)
    bg = Color(1)
    buf = height * 0.2

    def __init__(self, **options):
        # inherit from the base class
        Group.__init__(self, **options)

        # process the options if any
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)
        self.height = options.get("height", self.height)
        self.width = options.get("width", self.width)
        self.angle = options.get("angle", self.angle)

        # make the modulator
        modulator = Group()
        modulator.append(
            Path(
                P(0, 0),
                P(0, self.height),
                P(self.width, self.height),
                P(self.width, 0),
                closed=1,
                fg=self.fg,
                bg=self.bg,
            ))
        modulator.append(
            Path(
                P(0, -self.buf),
                P(self.width, -self.buf),
                fg=self.fg,
                bg=self.bg,
            ))
        modulator.append(
            Path(
                P(0, self.height + self.buf),
                P(self.width, self.height + self.buf),
                fg=self.fg,
                bg=self.bg,
            ))

        # rotate if necessary
        modulator.rotate(self.angle, p=modulator.bbox().c)

        self.append(modulator)
예제 #30
0
class Lens(Group):
    """
    A lens

    @ivar height: lens height
    @type height: float

    @ivar thickness: lens thickness
    @type thickness: float

    @ivar angle: rotation angle
    @type angle: float

    @ivar type: the type of lens: convex/concave
    @type type: string

    @ivar fg: foreground colour
    @type fg: L{Color} object

    @ivar bg: background colour
    @type bg: L{Color} object
    """

    height = 1.0
    thickness = 0.4
    angle = 0.0
    fg = Color(0)
    bg = Color(1)
    type = "concave"

    def __init__(self, **options):
        # inherit from the base class
        Group.__init__(self, **options)

        # process the options if any
        self.fg = options.get("fg", self.fg)
        self.bg = options.get("bg", self.bg)
        self.height = options.get("height", self.height)
        self.thickness = options.get("thickness", self.thickness)
        self.angle = options.get("angle", self.angle)
        self.type = options.get("type", self.type)

        # determine what type of lens to make
        if self.type == "convex":
            leftCurveAngle = -30
            rightCurveAngle = -30
        elif self.type == "concave":
            leftCurveAngle = 30
            rightCurveAngle = 30
        else:
            print "Unknown lens type, defaulting to concave"
            leftCurveAngle = 30
            rightCurveAngle = 30

        # make the lens
        lens = Group()
        lens.append(
            Path(
                P(0, 0),
                C(leftCurveAngle, 180 - leftCurveAngle),
                P(0, self.height),
                P(self.thickness, self.height),
                C(-180 + rightCurveAngle, -rightCurveAngle),
                P(self.thickness, 0),
                closed=1,
                fg=self.fg,
                bg=self.bg,
            ))

        # rotate if necessary
        lens.rotate(self.angle, p=lens.bbox().c)

        self.append(lens)