Ejemplo n.º 1
0
    def _draw_arc(self, inner_radius, outer_radius, startangle, endangle,
                 color, border=None, colour=None, **kwargs):
        """ draw_arc(self, inner_radius, outer_radius, startangle, endangle, color)
                -> Group

            o inner_radius  Float distance of inside of arc from drawing center

            o outer_radius  Float distance of outside of arc from drawing center

            o startangle    Float angle subtended by start of arc at drawing center
                            (in radians)

            o endangle      Float angle subtended by end of arc at drawing center
                            (in radians)

            o color        colors.Color object for arc (overridden by backwards
                           compatible argument with UK spelling, colour).

            Returns a closed path object describing an arced box corresponding to
            the passed values.  For very small angles, a simple four sided
            polygon is used.
        """
        #Let the UK spelling (colour) override the USA spelling (color)
        if colour is not None:
            color = colour

        if border is None:
            border = color

        if color is None:
            color = colour
        if color == colors.white and border is None:   # Force black border on 
            strokecolor = colors.black                 # white boxes with
        elif border is None:                           # undefined border, else
            strokecolor = color                        # use fill colour
        elif border is not None:
            strokecolor = border

        if abs(float(endangle - startangle))>.01:
            # Wide arc, must use full curves
            p = ArcPath(strokeColor=strokecolor,
                        fillColor=color,
                        strokewidth=0)
            #Note reportlab counts angles anti-clockwise from the horizontal
            #(as in mathematics, e.g. complex numbers and polar coordinates)
            #but we use clockwise from the vertical.  Also reportlab uses
            #degrees, but we use radians.
            p.addArc(self.xcenter, self.ycenter, inner_radius,
                     90 - (endangle * 180 / pi), 90 - (startangle * 180 / pi),
                     moveTo=True)
            p.addArc(self.xcenter, self.ycenter, outer_radius,
                     90 - (endangle * 180 / pi), 90 - (startangle * 180 / pi),
                     reverse=True)
            p.closePath()
            return p
        else:
            #Cheat and just use a four sided polygon.
            # Calculate trig values for angle and coordinates
            startcos, startsin = cos(startangle), sin(startangle)
            endcos, endsin = cos(endangle), sin(endangle)
            x0,y0 = self.xcenter, self.ycenter      # origin of the circle
            x1,y1 = (x0+inner_radius*startsin, y0+inner_radius*startcos)
            x2,y2 = (x0+inner_radius*endsin, y0+inner_radius*endcos)
            x3,y3 = (x0+outer_radius*endsin, y0+outer_radius*endcos)
            x4,y4 = (x0+outer_radius*startsin, y0+outer_radius*startcos)
            return draw_polygon([(x1,y1),(x2,y2),(x3,y3),(x4,y4)], color, border)
Ejemplo n.º 2
0
    def _draw_arc_arrow(self, inner_radius, outer_radius, startangle, endangle,
                  color, border=None,
                  shaft_height_ratio=0.4, head_length_ratio=0.5, orientation='right',
                  colour=None, **kwargs):
        """Draw an arrow along an arc."""
        #Let the UK spelling (colour) override the USA spelling (color)
        if colour is not None:
            color = colour

        if border is None:
            border = color

        if color is None:
            color = colour
        if color == colors.white and border is None:   # Force black border on 
            strokecolor = colors.black                 # white boxes with
        elif border is None:                           # undefined border, else
            strokecolor = color                        # use fill colour
        elif border is not None:
            strokecolor = border

        #if orientation == 'right':
        #    startangle, endangle = min(startangle, endangle), max(startangle, endangle)
        #elif orientation == 'left':
        #    startangle, endangle = max(startangle, endangle), min(startangle, endangle)
        #else :
        startangle, endangle = min(startangle, endangle), max(startangle, endangle)
        if orientation <> "left" and orientation <> "right" :
            raise ValueError("Invalid orientation %s, should be 'left' or 'right'" \
                             % repr(orientation))

        angle = float(endangle - startangle)    # angle subtended by arc
        middle_radius = 0.5*(inner_radius+outer_radius)
        boxheight = outer_radius - inner_radius
        shaft_height = boxheight*shaft_height_ratio
        shaft_inner_radius = middle_radius - 0.5*shaft_height
        shaft_outer_radius = middle_radius + 0.5*shaft_height
        headangle_delta = min(abs(asin(boxheight/middle_radius)*head_length_ratio), abs(angle))
        if angle < 0 :
            headangle_delta *= -1 #reverse it
        if orientation=="right" :
            headangle = endangle-headangle_delta
        else :
            headangle = startangle+headangle_delta
        if startangle <= endangle :
            headangle = max(min(headangle, endangle), startangle)
        else :
            headangle = max(min(headangle, startangle), endangle)
        assert startangle <= headangle <= endangle \
            or endangle <= headangle <= startangle
        

        # Calculate trig values for angle and coordinates
        startcos, startsin = cos(startangle), sin(startangle)
        headcos, headsin = cos(headangle), sin(headangle)
        endcos, endsin = cos(endangle), sin(endangle)
        x0,y0 = self.xcenter, self.ycenter      # origin of the circle
        if abs(headangle_delta) >= abs(angle) :
            #Cheat and just use a triangle.
            if orientation=="right" :
                x1,y1 = (x0+inner_radius*startsin, y0+inner_radius*startcos)
                x2,y2 = (x0+outer_radius*startsin, y0+outer_radius*startcos)
                x3,y3 = (x0+middle_radius*endsin, y0+middle_radius*endcos)
            else :
                x1,y1 = (x0+inner_radius*endsin, y0+inner_radius*endcos)
                x2,y2 = (x0+outer_radius*endsin, y0+outer_radius*endcos)
                x3,y3 = (x0+middle_radius*startsin, y0+middle_radius*startcos)
            return draw_polygon([(x1,y1),(x2,y2),(x3,y3)], color, border)
        elif orientation=="right" :
            p = ArcPath(strokeColor=strokecolor,
                        fillColor=color,
                        #default is mitre/miter which can stick out too much:
                        strokeLineJoin=1, #1=round
                        strokewidth=0)
            #Note reportlab counts angles anti-clockwise from the horizontal
            #(as in mathematics, e.g. complex numbers and polar coordinates)
            #but we use clockwise from the vertical.  Also reportlab uses
            #degrees, but we use radians.
            p.addArc(self.xcenter, self.ycenter, shaft_inner_radius,
                     90 - (headangle * 180 / pi), 90 - (startangle * 180 / pi),
                     moveTo=True)
            p.addArc(self.xcenter, self.ycenter, shaft_outer_radius,
                     90 - (headangle * 180 / pi), 90 - (startangle * 180 / pi),
                     reverse=True)
            p.lineTo(x0+outer_radius*headsin, y0+outer_radius*headcos)
            p.lineTo(x0+middle_radius*endsin, y0+middle_radius*endcos)
            p.lineTo(x0+inner_radius*headsin, y0+inner_radius*headcos)
            p.closePath()
            return p
        else :
            p = ArcPath(strokeColor=strokecolor,
                        fillColor=color,
                        #default is mitre/miter which can stick out too much:
                        strokeLineJoin=1, #1=round
                        strokewidth=0)
            #Note reportlab counts angles anti-clockwise from the horizontal
            #(as in mathematics, e.g. complex numbers and polar coordinates)
            #but we use clockwise from the vertical.  Also reportlab uses
            #degrees, but we use radians.
            p.addArc(self.xcenter, self.ycenter, shaft_inner_radius,
                     90 - (endangle * 180 / pi), 90 - (headangle * 180 / pi),
                     moveTo=True, reverse=True)
            p.addArc(self.xcenter, self.ycenter, shaft_outer_radius,
                     90 - (endangle * 180 / pi), 90 - (headangle * 180 / pi),
                     reverse=False)
            p.lineTo(x0+outer_radius*headsin, y0+outer_radius*headcos)
            p.lineTo(x0+middle_radius*startsin, y0+middle_radius*startcos)
            p.lineTo(x0+inner_radius*headsin, y0+inner_radius*headcos)
            p.closePath()
            return p