def draw_arrow( self, segment: Segment, length: float, height: float ): """ Draws a segment with an arrow in it's end. The arrow's dimensions are given by `length` and `height`. :param segment: `Segment` :param length: `Int` length of the arrow head :param height: `Int` height of the arrow head """ director = segment.direction_vector v_l = director.opposite().with_length(length) v_h1 = director.perpendicular().with_length(height / 2.0) v_h2 = v_h1.opposite() self.draw_segment(segment) self.draw_segment( Segment( segment.end, segment.end.displaced(v_l + v_h1) ) ) self.draw_segment( Segment( segment.end, segment.end.displaced(v_l + v_h2) ) )
def geometry(self): """ Line segment representing the geometry of the bar. :return: `Segment` """ return Segment(self.start_node.position, self.end_node.position)
def vector_to_svg( position: Point, vector: Vector, scale: float, color: str, config ): """ Creates an SVG representation of the given vector using an arrow and a label aligned with the arrow. :param position: origin of the vector :param vector: `Vector` :param scale: scale to use in the drawing :param color: color to use for the arrow and label :param config: configuration dictionary :return: SVG arrow and label """ segment = Segment( position.displaced(vector, -scale), position ) caption_origin = segment.start.displaced( segment.normal_versor, __CAPTION_DISP ) def svg_arrow(): width = config['sizes']['stroke'] arrow_size = config['sizes']['arrow'] return svg.arrow( segment, arrow_size, arrow_size, [ attributes.stroke_color(color), attributes.stroke_width(width), attributes.fill_color('none') ] ) def svg_caption(): return caption_to_svg( vector.to_formatted_str(__DECIMAL_POS), caption_origin, vector.angle_to(__I_VERSOR), color, config ) return svg.group([ svg_arrow(), svg_caption() ])
def final_geometry(self): """ The bar's geometry, described by a line segment, after the computed displacements are applied. :return: the solution bar's geometry """ return Segment( self.start_node.displaced_pos, self.end_node.displaced_pos )
def final_geometry_scaling_displacement(self, scale: float): """ Computes the geometry of the bar after the displacements of its nodes have been applied with a given scale factor. This scaled geometry can be used for drawing the solution diagram. :param scale: used to scale the displacements :return: the solution bar's final geometry scaled """ return Segment( self.start_node.displaced_pos_scaled(scale), self.end_node.displaced_pos_scaled(scale) )
def parse_segment(line): match = re.match(__SEGM_RE, line) return Segment(start=Point(float(match.group('sx')), float(match.group('sy'))), end=Point(float(match.group('ex')), float(match.group('ey'))))
def simulate(transform, primitives, config): # ---------- UI DEFINITION ---------- # tk = Tk() tk.title("Affine Transformations") tk.minsize(width=400, height=400) canvas = Canvas(tk) canvas.pack(fill='both', side='top', expand=True) def start_simulation(): tk.update() main_loop(update_system, redraw, should_continue) button = Button(tk, text='Play', command=start_simulation) button.pack(anchor='center', side='bottom') # ---------- UPDATE, DRAW & CONTINUE ---------- # frames = config['frames'] transform_seq = __make_transform_sequence(transform, frames) axis_length = config['axes']['length'] x_axis = Segment(Point(0, 0), Point(axis_length, 0)) y_axis = Segment(Point(0, 0), Point(0, axis_length)) drawing = CanvasDrawing(canvas, transform_seq[0]) def update_system(time_delta_s, time_s, frame): drawing.transform = transform_seq[frame - 1] tk.update() def redraw(): drawing.clear_drawing() drawing.outline_width = config['axes']['stroke-width'] drawing.outline_color = config['axes']['x-color'] drawing.draw_arrow(x_axis, config['axes']['arrow-length'], config['axes']['arrow-height']) drawing.outline_color = config['axes']['y-color'] drawing.draw_arrow(y_axis, config['axes']['arrow-length'], config['axes']['arrow-height']) drawing.outline_width = config['geometry']['stroke-width'] drawing.outline_color = config['geometry']['stroke-color'] for circle in primitives['circs']: drawing.draw_circle(circle) for rect in primitives['rects']: drawing.draw_rectangle(rect) for polygon in primitives['polys']: drawing.draw_polygon(polygon) for segment in primitives['segs']: drawing.draw_segment(segment) def should_continue(frame, time_s): return frame <= frames # ---------- MAIN LOOP ---------- # redraw() tk.mainloop()
def test_segment(self): segment = Segment(Point(2, 3), Point(4, 5)) actual = primitives.segment(segment) expected = '<line x1="2" y1="3" x2="4" y2="5" />' self.assertEqual(expected, actual)