Exemple #1
0
def get_dimension(text):
    """Return the bounding box of the <text>,
    assuming that the left-bottom corner
    of the first letter of the text is at (0, 0). This procedure ignores
    /h, /v, and /a directives when calculating the boundingbox; it just returns the
    alignment specifiers as a part of the return value. The return value is a
    tuple (width, height, halign, valign, angle)."""
    (xmax, ymax, halign, valign, angle) = unaligned_get_dimension(text)
    xmin = ymin = 0
    if halign == 'C':
        xmin = -xmax / 2.0
        xmax = xmax / 2.0
    elif halign == 'R':
        xmin = -xmax
        xmax = 0
    if valign == 'M':
        ymin = -ymax / 2.0
        ymax = ymax / 2.0
    elif valign == 'T':
        ymin = -ymax
        ymax = 0
    if angle != 0:
        (x0, y0) = pychart_util.rotate(xmin, ymin, angle)
        (x1, y1) = pychart_util.rotate(xmax, ymin, angle)
        (x2, y2) = pychart_util.rotate(xmin, ymax, angle)
        (x3, y3) = pychart_util.rotate(xmax, ymax, angle)
        xmax = max(x0, x1, x2, x3)
        xmin = min(x0, x1, x2, x3)
        ymax = max(y0, y1, y2, y3)
        ymin = min(y0, y1, y2, y3)
        return (xmin, xmax, ymin, ymax)
    return (xmin, xmax, ymin, ymax)
Exemple #2
0
    def draw(self, ar, can):
        center = self.center
        if not center:
            center = (ar.loc[0] + ar.size[0] / 2.0,
                      ar.loc[1] + ar.size[1] / 2.0)
        radius = self.radius
        if not radius:
            radius = min(ar.size[0] / 2.0, ar.size[1] / 2.0) * 0.5

        label_offset = radius + (self.label_offset or radius * 0.1)

        total = self._total()
        i = 0
        cur_angle = self.start_angle
        for val in self.data:
            fill = self.fill_styles[i]
            degree = 360 * float(val[self.data_col]) / float(total)

            off = (0, 0)
            if len(self.arc_offsets) > i:
                off = pychart_util.rotate(self.arc_offsets[i], 0,
                                          cur_angle - degree / 2.0)
            x_center = center[0] + off[0]
            y_center = center[1] + off[1]

            can.ellipsis(self.line_style, fill, x_center, y_center, radius, 1,
                         cur_angle - degree, cur_angle, self.shadow)

            label = pychart_util.apply_format(self.label_format, val,
                                              self.label_col)
            if label != None:
                (x_label,
                 y_label) = pychart_util.rotate(label_offset, 0,
                                                cur_angle - degree / 2.0)
                (x_arrowtip,
                 y_arrowtip) = pychart_util.rotate(radius, 0,
                                                   cur_angle - degree / 2.0)
                # Labels on left side of pie need
                # their text to avoid obscuring the pie
                if x_label < 0:
                    x_label = x_label - font.text_width(label)

                t = text_box.T(loc=(x_label + x_center, y_label + y_center),
                               text=label,
                               line_style=self.label_line_style,
                               fill_style=self.label_fill_style)
                if self.arrow_style:
                    t.add_arrow((x_arrowtip + x_center, y_arrowtip + y_center),
                                None, self.arrow_style)

                t.draw(can)
            cur_angle = (cur_angle - degree) % 360
            i = (i + 1) % len(self.fill_styles)
Exemple #3
0
    def __arcsub(self, x, y, radius, start, theta):
	xcos = math.cos(basecanvas.to_radian(theta))
	xsin = math.sin(basecanvas.to_radian(theta))
	x0 = radius * xcos
	y0 = radius * xsin
 	x1 = radius * (4-xcos)/3.0
 	y1 = radius * (1-xcos)*(xcos-3)/(3*xsin)

        xx0, xy0 = pychart_util.rotate(x0, y0, start+theta)
        xx1, xy1 = pychart_util.rotate(x1, -y1, start+theta)
        xx2, xy2 = pychart_util.rotate(x1, y1, start+theta)
	self.__write("%f %f %f %f %f %f c\n" %
		(x+xx1, y+xy1, x+xx2, y+xy2, x+xx0, y+xy0))
    def draw(self, ar, can):
        center = self.center
        if not center:
            center = (ar.loc[0] + ar.size[0]/2.0,
                      ar.loc[1] + ar.size[1]/2.0)
        radius = self.radius
        if not radius:
            radius = min(ar.size[0]/2.0, ar.size[1]/2.0) * 0.5

        label_offset = radius + (self.label_offset or radius * 0.1)
        
        total = self._total()
        i = 0
        cur_angle = self.start_angle
        for val in self.data:
            fill = self.fill_styles[i]
            degree = 360 * float(val[self.data_col]) / float(total)
            
            off = (0, 0)
            if len(self.arc_offsets) > i:
                off = pychart_util.rotate(self.arc_offsets[i], 0, cur_angle - degree/2.0)
            x_center = center[0]+ off[0]
            y_center = center[1]+ off[1]
            
            can.ellipsis(self.line_style, fill,
                         x_center, y_center, radius, 1,
                         cur_angle - degree, cur_angle,
                         self.shadow)

            label = pychart_util.apply_format(self.label_format, val,
                                              self.label_col)
            if label != None:
                (x_label, y_label) = pychart_util.rotate(label_offset, 0, cur_angle - degree/2.0)
                (x_arrowtip, y_arrowtip) = pychart_util.rotate(radius, 0, cur_angle - degree/2.0)
                # Labels on left side of pie need
                # their text to avoid obscuring the pie
                if x_label < 0:
                    x_label = x_label - font.text_width(label)

                t = text_box.T(loc = (x_label + x_center, y_label + y_center),
                               text = label,
                               line_style = self.label_line_style,
                               fill_style = self.label_fill_style)
                if self.arrow_style:
                    t.add_arrow((x_arrowtip + x_center, y_arrowtip + y_center),
                                None, self.arrow_style)

                t.draw(can)
            cur_angle = (cur_angle - degree) % 360
            i = (i + 1) % len(self.fill_styles)
    def draw(self, ar, can):
        center = self.center
        if not center:
            center = (ar.loc[0] + ar.size[0]/2.0,
                            ar.loc[1] + ar.size[1]/2.0)
        base_radius = self.base_radius # the maximum radius of a wedge
        if not base_radius:
            base_radius = min(ar.size[0]/2.0, ar.size[1]/2.0) #* 0.8

        sector_decrement = 1./(len(self.data)*2) * self.sector_width # each following sector diagram will have its sector width decremented by half this amount (in degrees)
        i = 0
        for dataset in self.data:
            cur_angle = self.start_angle
            if self.sector_centred:
                cur_angle -= self.sector_width/2.
            fill = self.fill_styles[i]
            x_center = center[0]
            y_center = center[1]

            if not i: # draw directions around sector diagram once off
                dir_offset = base_radius + (self.dir_offset or base_radius * 0.04)
                directions = ['N', 'E', 'S', 'W']
                angle = self.start_angle

                can.ellipsis(line_style.T(color=color.black, width=0.3, dash=line_style.dash1), None,
                             x_center, y_center, base_radius, 1,
                             0, 360) #

                for d in directions:
                    x_label, y_label = pychart_util.rotate(dir_offset, 0, angle) # coords for bottom left corner of box
                    tw = font.text_width(d)
                    half = 1/3. # normal arithmetic does not seem to apply to these text_box objects...
                    if (angle == 0): # east
                        y_label -= font.text_height(d)[0]*half # move down half
                    elif (angle == -180): # west
                        y_label -= font.text_height(d)[0]*half # move down half
                        x_label -= font.text_width(d) # move left full
                    elif (angle == 90): # north
                        x_label -= font.text_height(d)[0]*half # move left half
                    elif (angle == -90): # south
                        y_label -= font.text_height(d)[0]*.8 # move down (couldn't figure out how to set this dynamically so I fudged...)
                        x_label -= font.text_height(d)[0]*half # move left half
                    canvas.show(x_label + x_center, y_label + y_center, d)
                    angle -= 360/len(directions)

            for val in dataset[self.data_col]: # now draw the sectors
                radius = base_radius*val # scale the radius
                start = cur_angle-self.sector_width+i*sector_decrement
                stop = cur_angle-i*sector_decrement # these may seem confusing, but remember that we need to go counterclockwise

                can.ellipsis(self.line_style, fill,
                             x_center, y_center, radius, 1, start, stop, self.shadow) 
                cur_angle = (cur_angle - self.sector_width) % 360 # we want to go in anticlockwise direction (North, West, South, etc. as in meteorology)
            i = (i + 1) % len(self.fill_styles)
Exemple #6
0
    def draw(self, ar, can):
        center = self.center
        if not center:
            center = (ar.loc[0] + ar.size[0]/2.0,
                            ar.loc[1] + ar.size[1]/2.0)
        base_radius = self.base_radius # the maximum radius of a wedge
        if not base_radius:
            base_radius = min(ar.size[0]/2.0, ar.size[1]/2.0) #* 0.8

        sector_decrement = 1./(len(self.data)*2) * self.sector_width # each following sector diagram will have its sector width decremented by half this amount (in degrees)
        i = 0
        for dataset in self.data:
            cur_angle = self.start_angle
            if self.sector_centred:
                cur_angle -= self.sector_width/2.
            fill = self.fill_styles[i]
            x_center = center[0]
            y_center = center[1]

            if not i: # draw directions around sector diagram once off
                dir_offset = base_radius + (self.dir_offset or base_radius * 0.04)
                directions = ['N', 'E', 'S', 'W']
                angle = self.start_angle

                can.ellipsis(line_style.T(color=color.black, width=0.3, dash=line_style.dash1), None,
                             x_center, y_center, base_radius, 1,
                             0, 360) #

                for d in directions:
                    x_label, y_label = pychart_util.rotate(dir_offset, 0, angle) # coords for bottom left corner of box
                    tw = font.text_width(d)
                    half = 1/3. # normal arithmetic does not seem to apply to these text_box objects...
                    if (angle == 0): # east
                        y_label -= font.text_height(d)[0]*half # move down half
                    elif (angle == -180): # west
                        y_label -= font.text_height(d)[0]*half # move down half
                        x_label -= font.text_width(d) # move left full
                    elif (angle == 90): # north
                        x_label -= font.text_height(d)[0]*half # move left half
                    elif (angle == -90): # south
                        y_label -= font.text_height(d)[0]*.8 # move down (couldn't figure out how to set this dynamically so I fudged...)
                        x_label -= font.text_height(d)[0]*half # move left half
                    canvas.show(x_label + x_center, y_label + y_center, d)
                    angle -= 360/len(directions)

            for val in dataset[self.data_col]: # now draw the sectors
                radius = base_radius*val # scale the radius
                start = cur_angle-self.sector_width+i*sector_decrement
                stop = cur_angle-i*sector_decrement # these may seem confusing, but remember that we need to go counterclockwise

                can.ellipsis(self.line_style, fill,
                             x_center, y_center, radius, 1, start, stop, self.shadow) 
                cur_angle = (cur_angle - self.sector_width) % 360 # we want to go in anticlockwise direction (North, West, South, etc. as in meteorology)
            i = (i + 1) % len(self.fill_styles)
Exemple #7
0
    def show(self, x, y, str):
        global out
        y_org = y
        org_str = str

        if invisible_p(x, y):
            return

        (xmin, xmax, ymin, ymax) = font.get_dimension(str)

        # rectangle(line_style.default, None, x+xmin, y+ymin, x+xmax, y+ymax)
        # ellipsis(line_style.default, None, x, y, 1)
        self.setbb(x + xmin, y + ymin)
        self.setbb(x + xmax, y + ymax)

        (halign, valign, angle) = font.get_align(str)

        base_x = x
        base_y = y

        # Handle vertical alignment
        if valign == "B":
            y = font.unaligned_text_height(str)
        elif valign == "T":
            y = 0
        elif valign == "M":
            y = font.unaligned_text_height(str) / 2.0

        (xmin, xmax, ymin, ymax) = font.get_dimension(org_str)
        self.setbb(x + xmin, y_org + y + ymin)
        self.setbb(x + xmax, y_org + y + ymax)
        itr = font.text_iterator(None)

        max_width = 0

        lines = []
        for line in str.split('\n'):
            cur_width = 0
            cur_height = 0

            itr.reset(line)

            strs = []

            while 1:
                elem = itr.next()
                if not elem:
                    break

                (font_name, size, line_height, color, _h, _v, _a, str) = elem
                cur_width += font.line_width(font_name, size, str)
                max_width = max(cur_width, max_width)
                cur_height = max(cur_height, line_height)

                # replace '(' -> '\(', ')' -> '\)' to make
                # Postscript string parser happy.
                str = str.replace("(", "\\(")
                str = str.replace(")", "\\)")
                strs.append((font_name, size, color, str))
            lines.append((cur_width, cur_height, strs))

        for line in lines:
            cur_width, cur_height, strs = line
            cur_y = y - cur_height
            y = y - cur_height
            self.comment("cury: %d hei %d str %s\n" %
                         (cur_y, cur_height, strs))
            if halign == 'C':
                cur_x = -cur_width / 2.0
            elif halign == 'R':
                cur_x = -cur_width
            else:
                cur_x = 0

            rel_x, rel_y = pychart_util.rotate(cur_x, cur_y, angle)
            self.text_begin()
            self.text_moveto(xscale(base_x + rel_x), yscale(base_y + rel_y),
                             angle)
            for segment in strs:
                font_name, size, color, str = segment
                self.text_show(font_name, nscale(size), color, str)
            self.text_end()
Exemple #8
0
def show(x, y, str):
    global out
    y_org = y
    org_str = str

    if invisible_p(x, y):
        return

    (xmin, xmax, ymin, ymax) = font.get_dimension(str)
	
    # rectangle(line_style.default, None, x+xmin, y+ymin, x+xmax, y+ymax)
    # ellipsis(line_style.default, None, x, y, 1)
    setbb(x+xmin, y+ymin)
    setbb(x+xmax, y+ymax)
	
    (halign, valign, angle) = font.get_align(str)

    base_x = x
    base_y = y

    # Handle vertical alignment
    if valign == "B":
        y = font.unaligned_text_height(str)
    elif valign == "T":
        y = 0
    elif valign == "M":
        y = font.unaligned_text_height(str) / 2.0
        
    (xmin, xmax, ymin, ymax) = font.get_dimension(org_str)
    # print org_str, xmin, xmax, ymin, ymax, x, y_org, y
    setbb(x+xmin, y_org+y+ymin)
    setbb(x+xmax, y_org+y+ymax)
    
    itr = font.text_iterator(None)
    
    max_width = 0
    
    lines = []
    for line in string.split(str, '\n'):
        cur_width = 0
        cur_height = 0
		
        itr.reset(line)
        
        strs = []
        
        while 1:
            elem = itr.next()
            if not elem:
                break
			
            (font_name, size, line_height, color, _h, _v, _a, str) = elem
            cur_width = cur_width + font.line_width(font_name, size, str)
            max_width = max(cur_width, max_width)
            cur_height = max(cur_height, line_height)
            
            # replace '(' -> '\(', ')' -> '\)' to make
            # Postscript string parser happy.
            str = string.replace(str, "(", "\\(")
            str = string.replace(str, ")", "\\)")
            strs.append((font_name, size, color, str))
        lines.append((cur_width, cur_height, strs))
		
    for line in lines:
        cur_width, cur_height, strs = line
        cur_y = y - cur_height
        y = y - cur_height
        out.comment("cury: %d hei %d str %s\n" % (cur_y, cur_height, strs))
        if halign == 'C':
            cur_x = -cur_width/2.0
        elif halign == 'R':
            cur_x = -cur_width
        else:
            cur_x = 0

	rel_x, rel_y = pychart_util.rotate(cur_x, cur_y, angle)
        out.text_begin()
        out.text_moveto(xscale(base_x + rel_x),
                        yscale(base_y + rel_y), angle)
        for segment in strs:
            font_name, size, color, str = segment
            out.text_show(font_name, nscale(size), color, str)
        out.text_end()