コード例 #1
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def __init__(self, p1=P(0, 0), p2=0, **options):
     if isinstance(p1, P):
         c = p1
     else:
         c = P(p1, p2)
     Circle.__init__(self, **options)
     self.c = c
コード例 #2
0
ファイル: path.py プロジェクト: OryxLib/Oryx.FastAdmin
    def fit_curve(self, p0, p1):
        '''
        fit a natural looking spline to end slopes
        '''

        # first get the angles ...
        if type(self.c0) in [type(10), type(10.0)]:
            # turn this into a unit vector in that direction
            w0 = U(self.c0)
        elif isinstance(self.c0, R):
            # already have unit vectior
            w0 = self.c0
        elif isinstance(self.c0, P):
            # non-unit vector giving direction
            w0 = (self.c0 - p0)
        else:
            raise ValueError, "Unknown control type c0"

        if type(self.c1) in [type(10), type(10.0)]:
            # turn this into a unit vector in that direction
            w1 = U(self.c1)
        elif isinstance(self.c1, R):
            # already have unit vectior
            w1 = self.c1
        elif isinstance(self.c1, P):
            # non-unit vector giving direction
            w1 = (self.c1 - p1)
        else:
            raise ValueError, "Unknown control type c1"

        t = ((p1 - p0).arg - w0.arg) * pi / 180.
        p = -((-p1 + p0).arg - w1.arg) * pi / 180.

        a = self._a
        b = self._b
        c = self._c

        alpha = a * (sin(t) - b * sin(p)) * (sin(p) - b * sin(t)) * (cos(t) -
                                                                     cos(p))

        rho = (2 + alpha) / (1 + (1 - c) * cos(t) + c * cos(p))
        sigma = (2 - alpha) / (1 + (1 - c) * cos(p) + c * cos(t))

        c0 = P(
            p0.x + rho * ((p1.x - p0.x) * cos(t) -
                          (p1.y - p0.y) * sin(t)) / (3 * self.t0), p0.y + rho *
            ((p1.y - p0.y) * cos(t) + (p1.x - p0.x) * sin(t)) / (3 * self.t0))

        c1 = P(
            p0.x + (p1.x - p0.x) * (1 - sigma * cos(p) / (3 * self.t1)) -
            (p1.y - p0.y) * sigma * sin(p) / (3 * self.t1),
            p0.y + (p1.y - p0.y) * (1 - sigma * cos(p) / (3 * self.t1)) +
            (p1.x - p0.x) * sigma * sin(p) / (3 * self.t1))

        # only change if we were given an angle
        if type(self.c0) in [type(10), type(10.0)]:
            self.c0 = c0
        if type(self.c1) in [type(10), type(10.0)]:
            self.c1 = c1
コード例 #3
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
    def locus(self, angle, target=None):
        '''
        Set or get a point on the locus
        
        @param angle: locus point in degrees
            (Degrees clockwise from north)
        @type angle: float

        @param target: target point
        @return: 
            - target is None: point on circumference at that angle
            - else: set point to the target, and return reference
                    to object
        @rtype: self or P
        '''
        r = self.r
        x = r * sin(angle / 180.0 * pi)
        y = r * cos(angle / 180.0 * pi)
        l = P(x, y)

        if target is None:
            return self.itoe(l)
        else:
            self.move(target - self.locus(angle))
            return self
コード例 #4
0
ファイル: render.py プロジェクト: OryxLib/Oryx.FastAdmin
def render(*objects, **options):
    '''
    render the file

    @param objects: list of objects to render
    @type objects: list

    @param options: dictionary of options to use when rendering
    @type options: dict
    '''

    if not options.has_key('file'):
        raise LookupError, "No filename given"

    out = open(options['file'], "w")

    if len(objects) == 0:
        raise ValueError, "No objects to render!"
    elif len(objects) == 1:
        if isinstance(objects[0], Eps):
            obj = objects[0]
        elif isinstance(objects[0], Pages):
            obj = objects[0]
        elif isinstance(objects[0], Page):
            # wrap in Pages environment
            obj = apply(Pages, objects)
        else:
            # assume it's an eps and wrap
            obj = apply(Eps, objects)
    else:
        if isinstance(objects[0], Page):
            # assume we have pages
            obj = apply(Pages, objects)
        else:
            # we have an eps
            obj = apply(Eps, objects)

    if isinstance(obj, Eps):
        # Make the sw corner (0,0) since some brain-dead previewers
        # don't understand bounding-boxes
        x1, y1, x2, y2 = obj.bbox_pp()
        obj.move((P(0, 0) - P(x1, y1)) / float(defaults.units))

    obj.write(out)
    out.close()

    print "Wrote", options['file']
コード例 #5
0
 def area(self):
     '''
     return an area object same size as page in default units
     @rtype: Area
     '''
     d1, d2, w, h = self.bbox_pp()
     
     w, h = w/float(defaults.units), h/float(defaults.units)
     
     return Area(sw = P(0, 0), width = w, height = h)
コード例 #6
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
    def __init__(self, text="", **options):

        self.text = text

        print "Obtaining TeX object's boundingbox ..."

        # this should be a tempfile ?
        tempName = "temp1"
        fp = open("%s.tex" % tempName, "w")
        fp.write(defaults.tex_head)
        fp.write(text)
        fp.write(defaults.tex_tail)
        fp.close()

        foe = os.popen(defaults.tex_command % tempName)
        sys.stderr.write(foe.read(-1))
        sys.stderr.write('\n')
        # Help the user out by throwing the latex log to stderr
        if os.path.exists("%s.log" % tempName):
            fp = open("%s.log" % tempName, 'r')
            sys.stderr.write(fp.read(-1))
            fp.close()
        if foe.close() is not None:
            raise RuntimeError, "Latex Error"


        fi, foe = os.popen4("dvips -q -E -o %s.eps %s.dvi" % \
                (tempName, tempName))
        err = foe.read(-1)
        sys.stderr.write(err)
        sys.stderr.write('\n')
        fi.close()
        if len(err) > 0:
            raise RuntimeError, "dvips Error"

        fp = open("%s.eps" % tempName, "r")
        eps = fp.read(-1)
        fp.close()

        # grab boundingbox ... only thing we want at this stage
        bbox_so = re.search("\%\%boundingbox:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)",
                            eps, re.I)
        bbox = []
        for ii in bbox_so.groups():
            bbox.append(int(ii))

        self.width = (bbox[2] - bbox[0]) / float(defaults.units)
        self.height = (bbox[3] - bbox[1]) / float(defaults.units)

        # now we have a width and height we can initialise Area
        Area.__init__(self, **options)

        self.offset = -P(bbox[0], bbox[1]) / float(defaults.units)

        self.scale(self.iscale)
コード例 #7
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
    def __init__(self, file, **options):
        '''
        @param file: path to epsf file
        @type file: string

        @return: The eps figure as an area object
        '''

        self.file = file

        print "Loading %s" % file

        fp = open(file, 'r')
        self.all = fp.read(-1)
        fp.close()

        bbox_so = re.compile(
            "\%\%boundingbox:\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)",
            re.I | re.S)

        so = bbox_so.search(self.all)
        x1s, y1s, x2s, y2s = so.groups()

        d = float(defaults.units)
        x1 = float(x1s) / d
        y1 = float(y1s) / d
        x2 = float(x2s) / d
        y2 = float(y2s) / d

        self.offset = -P(x1, y1)

        self.width = x2 - x1
        self.height = y2 - y1

        # width and height have special meaning here
        if options.has_key('width') and options.has_key('height'):
            sx = options['width'] / float(self.width)
            sy = options['height'] / float(self.height)
            del options['width']
            del options['height']
        elif options.has_key('width'):
            sx = sy = options['width'] / float(self.width)
            del options['width']
        elif options.has_key('height'):
            sx = sy = options['height'] / float(self.height)
            del options['height']
        else:
            sx = sy = 1

        self.scale(sx, sy)

        Area.__init__(self, **options)
コード例 #8
0
ファイル: path.py プロジェクト: OryxLib/Oryx.FastAdmin
    def bbox(self, itoe=Identity):
        """
        Return the bounding box
        """

        p0 = itoe(self.s)
        p1 = itoe(self.e)

        x0 = min(p0[0], p1[0])
        x1 = max(p0[0], p1[0])
        y0 = min(p0[1], p1[1])
        y1 = max(p0[1], p1[1])

        return Bbox(sw=P(x0, y0), width=x1 - x0, height=y1 - y0)
コード例 #9
0
ファイル: arrowheads.py プロジェクト: OryxLib/Oryx.FastAdmin
    def bbox(self):
        """
        Return the bounding box of the Path
        """

        # the (0,0) point:
        p0 = self.itoe(P(0, 0))
        xmax = xmin = p0.x
        ymax = ymin = p0.y

        for bez in self.shape:

            c1x, c1y, c2x, c2y, p2x, p2y = bez
            p1 = self.itoe(P(c1x, c1y) / float(defaults.units))
            p2 = self.itoe(P(c2x, c2y) / float(defaults.units))
            p3 = self.itoe(P(p2x, p2y) / float(defaults.units))

            xmax = max(xmax, p1.x, p2.x, p3.x)
            xmin = min(xmin, p1.x, p2.x, p3.x)
            ymax = max(ymax, p1.y, p2.y, p3.y)
            ymin = min(ymin, p1.y, p2.y, p3.y)

        return Bbox(sw=P(xmin, ymin), width=xmax - xmin, height=ymax - ymin)
コード例 #10
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
    def bbox(self):
        """
        Return the bounding box of the object
        """

        x1, y1 = self.sw
        x2, y2 = self.ne

        for p in [self.sw, self.nw, self.ne, self.se]:
            x1 = min(x1, p[0])
            y1 = min(y1, p[1])
            x2 = max(x2, p[0])
            y2 = max(y2, p[1])

        return Bbox(sw=P(x1, y1), width=x2 - x1, height=y2 - y1)
コード例 #11
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
    def move(self, *args):
        '''
        translate object by a certain amount
        @param args: amount to move by, can be given as
         - dx,dy
         - P
        @return: reference to self
        @rtype: self
        '''
        if len(args) == 1:
            # assume we have a point
            self.o += args[0]
        else:
            # assume we have dx,dy
            self.o += P(args[0], args[1])

            return self
コード例 #12
0
ファイル: path.py プロジェクト: OryxLib/Oryx.FastAdmin
    def bbox(self, itoe=Identity):
        """
        Return the bounding box of the object
        """
        # run through the list of points to get the bounding box

        #if self.length is None:
        #    self._cache()

        p0 = itoe(self.s)
        x0, y0 = p0
        x1, y1 = p0

        for p in self._points:

            p1 = itoe(p)

            x0 = min(x0, p1[0])
            x1 = max(x1, p1[0])
            y0 = min(y0, p1[1])
            y1 = max(y1, p1[1])

        return Bbox(sw=P(x0, y0), width=x1 - x0, height=y1 - y0)
コード例 #13
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_c(self):
     """
     Get the "centre" point
     """
     return self.itoe(P(self.width / 2., self.height / 2.) + self.isw)
コード例 #14
0
ファイル: arrowheads.py プロジェクト: OryxLib/Oryx.FastAdmin
class ArrowHead(AffineObj):
    '''
    Arrow head object

    @cvar tip: where to position the tip of the arrow head
    @cvar angle: the direction to point

    Convenience variables modifying the head size:

    @cvar scalew: scale the width by this amount
    @cvar scaleh: scale height by this amount

    The actual shape of the arrowhead is defined by the following, distances
    are given in points
    
    @cvar start: tuple giving starting point for path
    @cvar shape: list of tuples giving arguments to postscripts curveto operator
    @cvar closed: whether to close the path or not
    @cvar fg: line color or None for no line
    @cvar bg: fill color or None for no fill
    @cvar linewidth: linewidth
    @cvar linejoin: 0=miter, 1=round, 2=bevel
    @cvar mitrelimit:  length of mitre of corners
    '''

    fg = Color(0)
    bg = Color(0)

    # used by Path object to set position and direction
    reverse = 0
    pos = 1

    tip = P(0, 0)
    angle = 0

    start = (0, 0)
    # triangular share in the Golden ratio
    # positions in pixels
    shape = [(0, 0, 1.5, -4.854, 1.5, -4.854),
             (1.5, -4.854, -1.5, -4.854, -1.5, -4.854),
             (-1.5, -4.854, 0, 0, 0, 0)]

    closed = 1

    scalew = 1
    scaleh = 1

    linewidth = 0.2
    linejoin = 2  #0=miter, 1=round, 2=bevel

    # miterlimit:
    # 1.414 cuts off miters at angles less than 90 degrees.
    # 2.0 cuts off miters at angles less than 60 degrees.
    # 10.0 cuts off miters at angles less than 11 degrees.
    # 1.0 cuts off miters at all angles, so that bevels are always produced
    miterlimit = 2

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

        # remember this angle for when instance is copied...
        # this assumes all rotations that have been applied
        # are represented by angle and reverse
        angle0 = self.angle + self.reverse * 180

        AffineObj.__init__(self, **options)

        if len(param) == 1:
            self.pos = param[0]

        sx = self.scalew
        sy = self.scaleh

        self.start = (self.start[0] * sx, self.start[1] * sy)

        shape = []
        for b in self.shape:
            shape.append((b[0] * sx, b[1] * sy, b[2] * sx, b[3] * sy,
                          b[4] * sx, b[5] * sy))
        self.shape = shape

        self.rotate(self.angle + self.reverse * 180 - angle0)

        self.move(self.tip)

    def body(self):
        """
        Return the postscript body of the Path
        """

        out = cStringIO.StringIO()

        if self.linewidth is not None:
            out.write("%g setlinewidth " % self.linewidth)

        if self.linejoin is not None:
            out.write("%d setlinejoin " % self.linejoin)

        if self.miterlimit is not None:
            out.write("%f setmiterlimit " % self.miterlimit)

        out.write('newpath %g %g moveto\n' % self.start)
        for bez in self.shape:
            out.write('%g %g %g %g %g %g curveto\n' % bez)

        if self.closed:
            out.write('closepath\n')

        if self.bg is not None:
            out.write("gsave %s fill grestore\n" % self.bg)

        if self.fg is not None:
            out.write("%s stroke\n" % self.fg)

        return out.getvalue()

    def bbox(self):
        """
        Return the bounding box of the Path
        """

        # the (0,0) point:
        p0 = self.itoe(P(0, 0))
        xmax = xmin = p0.x
        ymax = ymin = p0.y

        for bez in self.shape:

            c1x, c1y, c2x, c2y, p2x, p2y = bez
            p1 = self.itoe(P(c1x, c1y) / float(defaults.units))
            p2 = self.itoe(P(c2x, c2y) / float(defaults.units))
            p3 = self.itoe(P(p2x, p2y) / float(defaults.units))

            xmax = max(xmax, p1.x, p2.x, p3.x)
            xmin = min(xmin, p1.x, p2.x, p3.x)
            ymax = max(ymax, p1.y, p2.y, p3.y)
            ymin = min(ymin, p1.y, p2.y, p3.y)

        return Bbox(sw=P(xmin, ymin), width=xmax - xmin, height=ymax - ymin)
コード例 #15
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_sw(self):
     """
     Get the "south-west" point
     """
     return self.itoe(P(-self.r, -self.r))
コード例 #16
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_ne(self):
     """
     Get the "north-east" point
     """
     return self.itoe(P(self.width, self.height) + self.isw)
コード例 #17
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_nw(self):
     """
     Get the "nort-west" point
     """
     return self.itoe(P(-self.r, self.r))
コード例 #18
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_se(self):
     """
     Get the "south-east" point
     """
     return self.itoe(P(self.r, -self.r))
コード例 #19
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
class Area(AffineObj):
    """
    A Rectangular area defined by sw corner and width and height.
    
    defines the following compass points that can be set and retrived::

          nw--n--ne
          |       |
          w   c   e
          |       |
          sw--s--se

    The origin is the sw corner and the others are calculated from the
    width and height attributes.

    If a subclass should have the origin somewhere other than sw then
    overide the sw attribute to make it a function
    
    @cvar width: the width
    @cvar height: the height
    @cvar c: centre point (simillarly for n,ne etc)
    """

    #XXX allow the changing of sw corner away from origin eg Text

    isw = P(0, 0)
    width = 0
    height = 0

    # Dynamic locations
    def _get_n(self):
        """
        Get the "north" point
        """
        return self.itoe(P(self.width / 2., self.height) + self.isw)

    def _set_n(self, pe):
        """
        Set the "north" point
        """
        self.move(pe - self.n)

    n = property(_get_n, _set_n)

    def _get_ne(self):
        """
        Get the "north-east" point
        """
        return self.itoe(P(self.width, self.height) + self.isw)

    def _set_ne(self, pe):
        """
        Set the "north-east" point
        """
        self.move(pe - self.ne)

    ne = property(_get_ne, _set_ne)

    def _get_e(self):
        """
        Get the "east" point
        """
        return self.itoe(P(self.width, self.height / 2.) + self.isw)

    def _set_e(self, pe):
        """
        Set the "east" point
        """
        self.move(pe - self.e)

    e = property(_get_e, _set_e)

    def _get_se(self):
        """
        Get the "south-east" point
        """
        return self.itoe(P(self.width, 0) + self.isw)

    def _set_se(self, pe):
        """
        Set the "south-east" point
        """
        self.move(pe - self.se)

    se = property(_get_se, _set_se)

    def _get_s(self):
        """
        Get the "south" point
        """
        return self.itoe(P(self.width / 2., 0) + self.isw)

    def _set_s(self, pe):
        """
        Set the "south" point
        """
        self.move(pe - self.s)

    s = property(_get_s, _set_s)

    def _get_sw(self):
        """
        Get the "south-west" point
        """
        return self.itoe(self.isw)

    def _set_sw(self, pe):
        """
        Set the "south-west" point
        """
        self.move(pe - self.sw)

    sw = property(_get_sw, _set_sw)

    def _get_w(self):
        """
        Get the "west" point
        """
        return self.itoe(P(0, self.height / 2.) + self.isw)

    def _set_w(self, pe):
        """
        Set the "west" point
        """
        self.move(pe - self.w)

    w = property(_get_w, _set_w)

    def _get_nw(self):
        """
        Get the "north-west" point
        """
        return self.itoe(P(0, self.height) + self.isw)

    def _set_nw(self, pe):
        """
        Set the "north-west" point
        """
        self.move(pe - self.nw)

    nw = property(_get_nw, _set_nw)

    def _get_c(self):
        """
        Get the "centre" point
        """
        return self.itoe(P(self.width / 2., self.height / 2.) + self.isw)

    def _set_c(self, pe):
        """
        Set the "centre" point
        """
        self.move(pe - self.c)

    c = property(_get_c, _set_c)

    def bbox(self):
        """
        Return the bounding box of the object
        """

        x1, y1 = self.sw
        x2, y2 = self.ne

        for p in [self.sw, self.nw, self.ne, self.se]:
            x1 = min(x1, p[0])
            y1 = min(y1, p[1])
            x2 = max(x2, p[0])
            y2 = max(y2, p[1])

        return Bbox(sw=P(x1, y1), width=x2 - x1, height=y2 - y1)
コード例 #20
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_nw(self):
     """
     Get the "north-west" point
     """
     return self.itoe(P(0, self.height) + self.isw)
コード例 #21
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_n(self):
     """
     Get the "north" point
     """
     return self.itoe(P(self.width / 2., self.height) + self.isw)
コード例 #22
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
    def body(self):
        """
        Returns the object's postscript body
        """

        out = cStringIO.StringIO()

        if self.linewidth:
            out.write("%g setlinewidth " % self.linewidth)

        if self.dash is not None:
            out.write(str(self.dash))

        # make sure we have a sensible radius
        r = min(self.width / 2., self.height / 2., self.r)
        w = self.width
        h = self.height

        ATTR = {
            'bg': self.bg,
            'fg': self.fg,
            'width': w,
            'height': h,
            'r': r,
            'ne': P(w, h),
            'n': P(w / 2., h),
            'nw': P(0, h),
            'w': P(0, h / 2.),
            'sw': P(0, 0),
            's': P(w / 2., 0),
            'se': P(w, 0),
            'e': P(w, h / 2.),
        }

        if self.bg is not None:
            if self.r == 0:
                out.write("%(bg)s 0 0 %(width)g uu %(height)g uu rectfill\n"\
                        % ATTR)
            else:
                out.write("%(bg)s newpath %(w)s moveto\n" % ATTR)
                out.write("%(nw)s %(n)s %(r)s uu arcto 4 {pop} repeat\n" %
                          ATTR)
                out.write("%(ne)s %(e)s %(r)s uu arcto 4 {pop} repeat\n" %
                          ATTR)
                out.write("%(se)s %(s)s %(r)s uu arcto 4 {pop} repeat\n" %
                          ATTR)
                out.write("%(sw)s %(w)s %(r)s uu arcto 4 {pop} repeat\n" %
                          ATTR)
                out.write("closepath fill\n")

        if self.fg is not None:
            if self.r == 0:
                out.write("%(fg)s 0 0 %(width)g uu %(height)g uu rectstroke\n"\
                                % ATTR)
            else:
                out.write("%(fg)s newpath %(w)s moveto\n" % ATTR)
                out.write("%(nw)s %(n)s %(r)s uu arcto 4 {pop} repeat\n" %
                          ATTR)
                out.write("%(ne)s %(e)s %(r)s uu arcto 4 {pop} repeat\n" %
                          ATTR)
                out.write("%(se)s %(s)s %(r)s uu arcto 4 {pop} repeat\n" %
                          ATTR)
                out.write("%(sw)s %(w)s %(r)s uu arcto 4 {pop} repeat\n" %
                          ATTR)
                out.write("closepath stroke\n")

        return out.getvalue()
コード例 #23
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_se(self):
     """
     Get the "south-east" point
     """
     return self.itoe(P(self.width, 0) + self.isw)
コード例 #24
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_s(self):
     """
     Get the "south" point
     """
     return self.itoe(P(self.width / 2., 0) + self.isw)
コード例 #25
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
class AffineObj(PsObj):
    '''
    A base class for object that should implement affine
    transformations, this should apply to any object that draws
    on the page.
    '''

    o = P(0, 0)
    T = Matrix(1, 0, 0, 1)

    def concat(self, t, p=None):
        '''
        concat matrix t to tranformation matrix
        @param t: a 2x2 Matrix dectribing Affine transformation
        @param p: the origin for the transformation
        @return: reference to self
        @rtype: self
        '''

        # update transformation matrix
        self.T = t * self.T

        #if p is not None:
        #    o=self.o # o is in external co-ords
        #    self.move(p-o)
        #    self.move(t*(o-p))

        o = self.o  # o is in external co-ords

        # set origin at (0,0)
        self.move(-o)

        # move to transformed p id defined
        if p is not None:
            self.move(p)
            self.move(t * (-p))

        # move to transformed origin
        self.move(t * o)

        return self

    def move(self, *args):
        '''
        translate object by a certain amount
        @param args: amount to move by, can be given as
         - dx,dy
         - P
        @return: reference to self
        @rtype: self
        '''
        if len(args) == 1:
            # assume we have a point
            self.o += args[0]
        else:
            # assume we have dx,dy
            self.o += P(args[0], args[1])

            return self

    def rotate(self, angle, p=None):
        """
        rotate object, 
        the rotation is around p when supplied otherwise
        it's the objects origin

        @param angle: angle in degrees, clockwise
        @param p: point to rotate around (external co-ords)
        @return: reference to self
        @rtype: self
        """
        angle = angle / 180.0 * pi  # convert angle to radians
        t = Matrix(cos(angle), sin(angle), -sin(angle), cos(angle))
        self.concat(t, p)

        return self

    def scale(self, sx, sy=None, p=None):
        '''
        scale object size (towards objects origin or p)
        @param sx: x scale factor, or total scale factor if sy=None
        @param sy: y scale factor
        @param p: point around which to scale
        @return: reference to self
        @rtype: self
        '''
        if sy is None:
            sy = sx

        t = Matrix(sx, 0, 0, sy)
        self.concat(t, p)

        return self

    def reflect(self, angle, p=None):
        '''
        reflect object in mirror
        @param angle: angle of mirror (deg clockwise from top)
        @param p: origin of reflection
        @return: reference to self
        @rtype: self
        '''
        # convert angle to radians, clockwise from top
        angle = angle / 180.0 * pi - pi / 2

        t = Matrix(
            cos(angle)**2 - sin(angle)**2, -2 * sin(angle) * cos(angle),
            -2 * sin(angle) * cos(angle),
            sin(angle)**2 - cos(angle)**2)

        self.concat(t, p)

        return self

    def shear(self, s, angle, p=None):
        '''
        shear object
        @param s: amount of shear
        @param angle: direction of shear (deg clockwise from top)
        @param p: origin of shear
        @return: reference to self
        @rtype: self
        '''

        self.rotate(angle, p)

        t = Matrix(1, 0, -s, 1)
        self.concat(t, p)

        self.rotate(-angle, p)

        return self

    def itoe(self, p_i):
        '''
        convert internal to external co-ords
        @param p_i: internal co-ordinate
        @return: external co-ordinate
        @rtype: P
        '''
        assert isinstance(p_i, P), "object not a P()"

        return self.T * p_i + self.o

    def etoi(self, p_e):
        '''
        convert external to internal co-ords
        @param p_e: external co-ordinate
        @return: internal co-ordinate
        @rtype: P
        '''
        assert isinstance(p_e, P), "object not a P()"

        return self.T.inverse() * (p_e - self.o)

    def prebody(self):
        '''
        set up transformation of coordinate system
        @rtype: string
        '''
        T = self.T
        o = self.o
        S = "gsave "
        if T == Matrix(1, 0, 0, 1):
            S = S + "%s translate\n" % o
        else:
            # NB postscript matrix is the transpose of what you'd expect!
            S = S + "[%g %g %g %g %s] concat\n" % (T[0], T[2], T[1], T[3], o())
        return S

    def postbody(self):
        '''
        undo coordinate system transformation
        @rtype: string
        '''
        return "grestore\n"
コード例 #26
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_e(self):
     """
     Get the "east" point
     """
     return self.itoe(P(self.width, self.height / 2.) + self.isw)
コード例 #27
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_ne(self):
     """
     Get the "nort-east" point
     """
     return self.itoe(P(self.r, self.r))
コード例 #28
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
    def _typeset(self):
        """
        Typeset the Text object (including kerning info)
        """

        string = self.text
        afm = AFM(self._font)

        # set the correct postscript font name
        self._font = afm.FontName

        size = self.size
        sc = size / 1000.

        chars = map(ord, list(string))

        # order: width l b r t

        # use 'reduce' and 'map' as they're written in C

        # add up all the widths
        width = reduce(lambda x, y: x + afm[y][0], chars, 0)

        # subtract the kerning
        if self.kerning == 1:
            if len(chars) > 1:
                kerns = map(lambda x, y: afm[(x, y)], chars[:-1], chars[1:])

                charlist = list(string)

                out = "("
                for ii in kerns:
                    if ii != 0:
                        out += charlist.pop(0) + ") %s (" % str(ii * sc)
                    else:
                        out += charlist.pop(0)
                out += charlist.pop(0) + ")"

                settext = out

                kern = reduce(lambda x, y: x + y, kerns)

                width += kern
            else:
                # this is to catch the case when there are no characters
                # in the string, but self.kerning==1
                settext = "(" + string + ")"

        else:
            settext = "(" + string + ")"

        # get rid of the end bits
        start = afm[chars[0]][1]
        f = afm[chars[-1]]
        width = width - start - (f[0] - f[3])

        # accumulate maximum height
        top = reduce(lambda x, y: max(x, afm[y][4]), chars, 0)

        # accumulate lowest point
        bottom = reduce(lambda x, y: min(x, afm[y][2]), chars,
                        afm[chars[0]][2])

        x1 = start * sc
        y1 = bottom * sc
        x2 = x1 + width * sc
        y2 = top * sc

        self.settext = settext
        self.offset = -P(x1, y1) / float(defaults.units)
        self.width = (x2 - x1) / float(defaults.units)
        self.height = (y2 - y1) / float(defaults.units)
コード例 #29
0
ファイル: objects.py プロジェクト: OryxLib/Oryx.FastAdmin
 def _get_w(self):
     """
     Get the "west" point
     """
     return self.itoe(P(0, self.height / 2.) + self.isw)