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)
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