def draw_Or(image, x, y, construct, options, forward): if len(construct.constructs) == 1: return draw(image, x, y, construct.constructs[0], options, forward) width, height, line_position = size_of_Or(image, construct, options) constructs = construct.constructs sizes = [size_of(image, c, options) for c in constructs] max_width = max(sizes, key=lambda (w, h, l): w)[0] radius = options.raildraw_or_radius spacing = options.raildraw_or_spacing arrow_width, arrow_height = options.raildraw_size_of_arrow(options) before = options.raildraw_or_before after = options.raildraw_or_after if not forward: before, after = after, before current_y = y for index, (c, (w, h, l)) in enumerate(zip(constructs, sizes)): draw_arrows = not isinstance(c, rr.Nothing) # Don't draw arrows if c is a loop and its component is not Nothing; # the arrows tend to appear superfluous in such a case if isinstance(c, rr.Loop) and not isinstance(c.component, rr.Nothing): draw_arrows = False if index != 0: image.move_to(x + radius, current_y + l - radius) image.arc_negative(x + radius * 2, current_y + l - radius, radius, radians(180), radians(90)) image.stroke() if not draw_arrows: draw_line(image, x + radius * 2, current_y + l, x + radius * 2 + arrow_width, current_y + l) else: options.raildraw_draw_arrow(image, x + radius * 2, current_y + l - (arrow_height / 2), options, forward) draw_line(image, x + radius * 2 + arrow_width, current_y + l, x + radius * 2 + arrow_width + before, current_y + l) construct_x = x + radius * 2 + arrow_width + before if isinstance(c, rr.Nothing): draw_line(image, construct_x, current_y + l, construct_x + max_width / 2 - w / 2, current_y + l) draw(image, construct_x + max_width / 2 - w / 2, current_y, c, options, forward) draw_line(image, construct_x + max_width / 2 + w / 2, current_y + l, construct_x + max_width + after, current_y + l) else: draw(image, construct_x, current_y, c, options, forward) draw_line(image, construct_x + w, current_y + l, construct_x + max_width + after, current_y + l) if not draw_arrows: draw_line(image, construct_x + max_width + after, current_y + l, construct_x + max_width + after + arrow_width, current_y + l) else: options.raildraw_draw_arrow(image, construct_x + max_width + after, current_y + l - (arrow_height / 2), options, forward) if index != 0: image.move_to(construct_x + max_width + after + arrow_width, current_y + l) image.arc_negative(construct_x + max_width + after + arrow_width, current_y + l - radius, radius, radians(90), radians(0)) image.stroke() if index == len(constructs) - 1: # Last construct line_end_y = current_y + l - radius current_y += spacing + h image.move_to(x, y + line_position) image.arc(x, y + line_position + radius, radius, radians(270), radians(0)) image.line_to(x + radius, line_end_y) image.stroke() draw_line(image, x, y + line_position, x + radius * 2, y + line_position) end_x = x + radius * 2 + arrow_width + before + max_width + after + arrow_width draw_line(image, end_x, y + line_position, end_x + radius * 2, y + line_position) image.move_to(x + width, y + line_position) image.arc_negative(x + width, y + line_position + radius, radius, radians(270), radians(180)) image.line_to(x + width - radius, line_end_y) image.stroke()
def draw_Then(image, x, y, construct, options, forward): constructs = construct.constructs arrow_before = options.raildraw_then_before_arrow arrow_after = options.raildraw_then_after_arrow if not forward: constructs = list(reversed(constructs)) arrow_before, arrow_after = arrow_after, arrow_before arrow_width, arrow_height = options.raildraw_size_of_arrow(options) width, height, line_position = size_of_Then(image, construct, options) current_x = x for index, c in enumerate(constructs): c_width, c_height, c_line_position = size_of(image, c, options) draw(image, current_x, y + (line_position - c_line_position), c, options, forward) current_x += c_width if index != (len(constructs) - 1): draw_line(image, current_x, y + line_position, current_x + arrow_before, y + line_position) current_x += arrow_before options.raildraw_draw_arrow(image, current_x, y + line_position - (arrow_height / 2), options, forward) current_x += arrow_width draw_line(image, current_x, y + line_position, current_x + arrow_after, y + line_position) current_x += arrow_after
def draw_Loop(context, x, y, construct, options, forward): component = construct.component delimiter = construct.delimiter c_width, c_height, c_line_pos = size_of(context, component, options) d_width, d_height, d_line_pos = size_of(context, delimiter, options) c_arrow = not isinstance(component, rr.Nothing) d_arrow = not isinstance(delimiter, rr.Nothing) # For now, if the delimiter is Nothing, don't draw the component's arrows if not d_arrow: c_arrow = False spacing = options.raildraw_loop_spacing radius = options.raildraw_loop_radius before = options.raildraw_loop_before after = options.raildraw_loop_after arrow_width, arrow_height = options.raildraw_size_of_arrow(options) d_y = y + c_height + spacing width, height, line_pos = size_of_Loop(context, construct, options) max_width = max(c_width, d_width) center_x = x + radius * 2 + arrow_width + before + (max_width / 2) draw_line(context, x, y + line_pos, x + radius * 2, y + line_pos) draw_arrow_or_line(context, x + radius * 2, y + line_pos - arrow_height / 2, arrow_width, arrow_height, options, forward, c_arrow) draw_line(context, x + radius * 2 + arrow_width, y + line_pos, center_x - c_width / 2, y + line_pos) draw(context, center_x - c_width / 2, y, component, options, forward) draw_line(context, center_x + c_width / 2, y + line_pos, x + width - radius * 2 - arrow_width, y + line_pos) draw_arrow_or_line(context, x + width - radius * 2 - arrow_width, y + line_pos - arrow_height / 2, arrow_width, arrow_height, options, forward, c_arrow) draw_line(context, x + width - radius * 2, y + line_pos, x + width, y + line_pos) # Component and its two arrows and line drawn. Now draw the curve down and # the delimiter, and its arrows and lines. context.move_to(x + radius * 2, y + line_pos) context.arc_negative(x + radius * 2, y + line_pos + radius, radius, radians(270), radians(180)) context.line_to(x + radius, d_y + d_line_pos - radius) context.arc_negative(x + radius * 2, d_y + d_line_pos - radius, radius, radians(180), radians(90)) context.stroke() draw_arrow_or_line(context, x + radius * 2, d_y + d_line_pos - arrow_height / 2, arrow_width, arrow_height, options, not forward, d_arrow) draw_line(context, x + radius * 2 + arrow_width, d_y + d_line_pos, center_x - d_width / 2, d_y + d_line_pos) draw(context, center_x - d_width / 2, d_y, delimiter, options, not forward) draw_line(context, center_x + d_width / 2, d_y + d_line_pos, x + width - radius * 2 - arrow_width, d_y + d_line_pos) draw_arrow_or_line(context, x + width - radius * 2 - arrow_width, d_y + d_line_pos - arrow_height / 2, arrow_width, arrow_height, options, not forward, d_arrow) context.move_to(x + width - radius * 2, d_y + d_line_pos) context.arc_negative(x + width - radius * 2, d_y + d_line_pos - radius, radius, radians(90), radians(0)) context.line_to(x + width - radius, y + line_pos + radius) context.arc_negative(x + width - radius * 2, y + line_pos + radius, radius, radians(0), radians(270)) context.stroke()
def size_of_Then(image, construct, options): constructs = construct.constructs sizes = [size_of(image, c, options) for c in constructs] before_heights = [l for w, h, l in sizes] after_heights = [h - l for w, h, l in sizes] max_before = max(before_heights) max_after = max(after_heights) arrow_line_size = (options.raildraw_then_before_arrow + options.raildraw_size_of_arrow(options)[0] + options.raildraw_then_after_arrow) return sum([w for w, h, l in sizes]) + (len(sizes) - 1) * arrow_line_size, max_before + max_after, max_before
def size_of_Or(image, construct, options): constructs = construct.constructs sizes = [size_of(image, c, options) for c in constructs] max_width = max(sizes, key=lambda (w, h, l): w)[0] total_height = sum([h for w, h, l in sizes]) arrow_width, arrow_height = options.raildraw_size_of_arrow(options) width = ((options.raildraw_or_radius * 4) + options.raildraw_or_before + max_width + options.raildraw_or_after + (arrow_width * 2)) height = total_height + ((len(constructs) - 1) * options.raildraw_or_spacing) # Line position of Or is the line position of its first construct return width, height, sizes[0][2]
def size_of_Then(image, construct, options): constructs = construct.constructs sizes = [size_of(image, c, options) for c in constructs] before_heights = [l for w, h, l in sizes] after_heights = [h - l for w, h, l in sizes] max_before = max(before_heights) max_after = max(after_heights) arrow_line_size = (options.raildraw_then_before_arrow + options.raildraw_size_of_arrow(options)[0] + options.raildraw_then_after_arrow) return sum([ w for w, h, l in sizes ]) + (len(sizes) - 1) * arrow_line_size, max_before + max_after, max_before
def size_of_Loop(image, construct, options): component = construct.component delimiter = construct.delimiter c_width, c_height, c_line_pos = size_of(image, component, options) d_width, d_height, d_line_pos = size_of(image, delimiter, options) radius = options.raildraw_loop_radius before = options.raildraw_loop_before after = options.raildraw_loop_after arrow_width, arrow_height = options.raildraw_size_of_arrow(options) width = radius * 2 + arrow_width + before + max(c_width, d_width) + after + arrow_width + radius * 2 height = c_height + options.raildraw_loop_spacing + d_height line_pos = c_line_pos return width, height, line_pos
def size_of_Loop(image, construct, options): component = construct.component delimiter = construct.delimiter c_width, c_height, c_line_pos = size_of(image, component, options) d_width, d_height, d_line_pos = size_of(image, delimiter, options) radius = options.raildraw_loop_radius before = options.raildraw_loop_before after = options.raildraw_loop_after arrow_width, arrow_height = options.raildraw_size_of_arrow(options) width = radius * 2 + arrow_width + before + max( c_width, d_width) + after + arrow_width + radius * 2 height = c_height + options.raildraw_loop_spacing + d_height line_pos = c_line_pos return width, height, line_pos
def size_of_Or(image, construct, options): constructs = construct.constructs if len(constructs) == 1: return size_of(image, constructs[0], options) sizes = [size_of(image, c, options) for c in constructs] max_width = max(sizes, key=itemgetter(0))[0] total_height = sum([h for w, h, l in sizes]) arrow_width, arrow_height = options.raildraw_size_of_arrow(options) width = ((options.raildraw_or_radius * 4) + options.raildraw_or_before + max_width + options.raildraw_or_after + (arrow_width * 2)) height = total_height + ( (len(constructs) - 1) * options.raildraw_or_spacing) # Line position of Or is the line position of its first construct return width, height, sizes[0][2]
def draw_Loop(image, x, y, construct, options, forward): component = construct.component delimiter = construct.delimiter c_width, c_height, c_line_pos = size_of(image, component, options) d_width, d_height, d_line_pos = size_of(image, delimiter, options) c_arrow = not isinstance(component, rr.Nothing) d_arrow = not isinstance(delimiter, rr.Nothing) # For now, if the delimiter is Nothing, don't draw the component's arrows if not d_arrow: c_arrow = False spacing = options.raildraw_loop_spacing radius = options.raildraw_loop_radius before = options.raildraw_loop_before after = options.raildraw_loop_after arrow_width, arrow_height = options.raildraw_size_of_arrow(options) d_y = y + c_height + spacing width, height, line_pos = size_of_Loop(image, construct, options) max_width = max(c_width, d_width) center_x = x + radius * 2 + arrow_width + before + (max_width / 2) draw_line(image, x, y + line_pos, x + radius * 2, y + line_pos) draw_arrow_or_line(image, x + radius * 2, y + line_pos - arrow_height / 2, arrow_width, arrow_height, options, forward, c_arrow) draw_line(image, x + radius * 2 + arrow_width, y + line_pos, center_x - c_width / 2, y + line_pos) draw(image, center_x - c_width / 2, y, component, options, forward) draw_line(image, center_x + c_width / 2, y + line_pos, x + width - radius * 2 - arrow_width, y + line_pos) draw_arrow_or_line(image, x + width - radius * 2 - arrow_width, y + line_pos - arrow_height / 2, arrow_width, arrow_height, options, forward, c_arrow) draw_line(image, x + width - radius * 2, y + line_pos, x + width, y + line_pos) # Component and its two arrows and line drawn. Now draw the curve down and # the delimiter, and its arrows and lines. image.move_to(x + radius * 2, y + line_pos) image.arc_negative(x + radius * 2, y + line_pos + radius, radius, radians(270), radians(180)) image.line_to(x + radius, d_y + d_line_pos - radius) image.arc_negative(x + radius * 2, d_y + d_line_pos - radius, radius, radians(180), radians(90)) image.stroke() draw_arrow_or_line(image, x + radius * 2, d_y + d_line_pos - arrow_height / 2, arrow_width, arrow_height, options, not forward, d_arrow) draw_line(image, x + radius * 2 + arrow_width, d_y + d_line_pos, center_x - d_width / 2, d_y + d_line_pos) draw(image, center_x - d_width / 2, d_y, delimiter, options, not forward) draw_line(image, center_x + d_width / 2, d_y + d_line_pos, x + width - radius * 2 - arrow_width, d_y + d_line_pos) draw_arrow_or_line(image, x + width - radius * 2 - arrow_width, d_y + d_line_pos - arrow_height / 2, arrow_width, arrow_height, options, not forward, d_arrow) image.move_to(x + width - radius * 2, d_y + d_line_pos) image.arc_negative(x + width - radius * 2, d_y + d_line_pos - radius, radius, radians(90), radians(0)) image.line_to(x + width - radius, y + line_pos + radius) image.arc_negative(x + width - radius * 2, y + line_pos + radius, radius, radians(0), radians(270)) image.stroke()
def draw_Or(image, x, y, construct, options, forward): if len(construct.constructs) == 1: return draw(image, x, y, construct.constructs[0], options, forward) width, height, line_position = size_of_Or(image, construct, options) constructs = construct.constructs sizes = [size_of(image, c, options) for c in constructs] max_width = max(sizes, key=itemgetter(0))[0] radius = options.raildraw_or_radius spacing = options.raildraw_or_spacing arrow_width, arrow_height = options.raildraw_size_of_arrow(options) before = options.raildraw_or_before after = options.raildraw_or_after if not forward: before, after = after, before current_y = y for index, (c, (w, h, l)) in enumerate(zip(constructs, sizes)): draw_arrows = not isinstance(c, rr.Nothing) # Don't draw arrows if c is a loop and its component is not Nothing; # the arrows tend to appear superfluous in such a case if isinstance(c, rr.Loop) and not isinstance(c.component, rr.Nothing): draw_arrows = False if index != 0: image.move_to(x + radius, current_y + l - radius) image.arc_negative(x + radius * 2, current_y + l - radius, radius, radians(180), radians(90)) image.stroke() if not draw_arrows: draw_line(image, x + radius * 2, current_y + l, x + radius * 2 + arrow_width, current_y + l) else: options.raildraw_draw_arrow(image, x + radius * 2, current_y + l - (arrow_height / 2), options, forward) draw_line(image, x + radius * 2 + arrow_width, current_y + l, x + radius * 2 + arrow_width + before, current_y + l) construct_x = x + radius * 2 + arrow_width + before if isinstance(c, rr.Nothing): draw_line(image, construct_x, current_y + l, construct_x + max_width / 2 - w / 2, current_y + l) draw(image, construct_x + max_width / 2 - w / 2, current_y, c, options, forward) draw_line(image, construct_x + max_width / 2 + w / 2, current_y + l, construct_x + max_width + after, current_y + l) else: draw(image, construct_x, current_y, c, options, forward) draw_line(image, construct_x + w, current_y + l, construct_x + max_width + after, current_y + l) if not draw_arrows: draw_line(image, construct_x + max_width + after, current_y + l, construct_x + max_width + after + arrow_width, current_y + l) else: options.raildraw_draw_arrow(image, construct_x + max_width + after, current_y + l - (arrow_height / 2), options, forward) if index != 0: image.move_to(construct_x + max_width + after + arrow_width, current_y + l) image.arc_negative(construct_x + max_width + after + arrow_width, current_y + l - radius, radius, radians(90), radians(0)) image.stroke() if index == len(constructs) - 1: # Last construct line_end_y = current_y + l - radius current_y += spacing + h image.move_to(x, y + line_position) image.arc(x, y + line_position + radius, radius, radians(270), radians(0)) image.line_to(x + radius, line_end_y) image.stroke() draw_line(image, x, y + line_position, x + radius * 2, y + line_position) end_x = x + radius * 2 + arrow_width + before + max_width + after + arrow_width draw_line(image, end_x, y + line_position, end_x + radius * 2, y + line_position) image.move_to(x + width, y + line_position) image.arc_negative(x + width, y + line_position + radius, radius, radians(270), radians(180)) image.line_to(x + width - radius, line_end_y) image.stroke()
def size_of_Nothing(image, construct, options): width, height = options.raildraw_size_of_arrow(options) return width, height, height / 2