def draw_polygon(ctx: Context, polygon: Polygon): if hasattr(polygon.exterior, 'coords'): start = True ctx.new_path() for x, y in polygon.exterior.coords: if start: ctx.move_to(x, y) else: ctx.line_to(x, y) start = False for interior in polygon.interiors: ctx.new_sub_path() start = True for x, y in interior.coords: if start: ctx.move_to(x, y) else: ctx.line_to(x, y) start = False ctx.close_path() ctx.close_path()
def export_svg(fn, paths, size, line_with=0.1, scale_factor=None): from cairocffi import SVGSurface, Context from .ddd import spatial_sort_2d as sort if not scale_factor: scale_factor = size s = SVGSurface(fn, size, size) c = Context(s) c.set_line_width(0.1) paths = sort(paths) for path in paths: path *= scale_factor c.new_path() c.move_to(*path[0,:]) for p in path[1:]: c.line_to(*p) c.stroke() c.save()
def label_train_spaces(ctx: cairo.Context, train: trains.Train, radius_factors=1, broken_spaces: Sequence = None): """Draw material name and thickness of the spaces. Args: radius_factors (scalar or sequence): Factor by which the average interface radii is multiplied to place the text. If a scalar is given it is broadcast. """ spaces, brokens = break_spaces(train.spaces, broken_spaces) radius_factors = np.broadcast_to(radius_factors, (len(spaces), )) radius_last = train.interfaces[0].radius y_last = 0 h_last = 0 n = train.interfaces[0].n1 for space, next_interface, radius_factor in zip( spaces, train.interfaces + (None, ), radius_factors): if next_interface is None: radius_next = radius_last h_next = 0 else: radius_next = next_interface.radius h_next = functions.calc_sphere_sag(next_interface.roc, radius_next) y_next = y_last + space if space != 0: string = '%.3f mm %s' % (space * 1e3, n.name) radius = (radius_last + radius_next) / 2 x = radius_factor * radius y = (y_next + h_next + y_last + h_last) / 2 ctx.save() ctx.translate(x, y) ctx.show_text(string) ctx.new_path() ctx.restore() if radius_factor > 1: draw_polyline(ctx, ((radius, y), (x, y))) ctx.stroke() y_last = y_next h_last = h_next if next_interface is not None: n = next_interface.n2 radius_last = next_interface.radius
def label_interface(ctx: cairo.Context, face: trains.Interface, radius_factor=1): """Draw text saying ROC, and a line from the edge of the interface to the text. Args: radius_factor (scalar): Factor by which interface radius is multiplied to get text x position. """ x = radius_factor * face.radius y = functions.calc_sphere_sag(face.roc, face.radius) string = 'ROC %.3f mm' % (face.roc * 1e3) ctx.set_source_rgb(0, 0, 0) ctx.save() ctx.translate(x, y) ctx.show_text(string) ctx.new_path() ctx.restore() if radius_factor > 1: draw_polyline(ctx, ((face.radius, y), (x, y))) ctx.stroke()
def rounded_rectangle(ctx: cairo.Context, x, y, w, h, rx, ry): # https://www.cairographics.org/cookbook/roundedrectangles/ arc_to_bezier = 0.55228475 if rx > w - rx: rx = w / 2 if ry > h - ry: ry = h / 2 c1 = arc_to_bezier * rx c2 = arc_to_bezier * ry ctx.new_path() ctx.move_to(x + rx, y) ctx.rel_line_to(w - 2 * rx, 0.0) ctx.rel_curve_to(c1, 0.0, rx, c2, rx, ry) ctx.rel_line_to(0, h - 2 * ry) ctx.rel_curve_to(0.0, c2, c1 - rx, ry, -rx, ry) ctx.rel_line_to(-w + 2 * rx, 0) ctx.rel_curve_to(-c1, 0, -rx, -c2, -rx, -ry) ctx.rel_line_to(0, -h + 2 * ry) ctx.rel_curve_to(0.0, -c2, rx - c1, -ry, rx, -ry) ctx.close_path()
def __draw_ring (self: 'HueSatWheelWidget', cr: cairocffi.Context, width: int, height: int, center_x: float, center_y: float, outer: float, inner: float) -> None: self.__redraw = False stride = cairocffi.ImageSurface.format_stride_for_width (cairocffi.FORMAT_ARGB32, width) buf = numpy.empty (int (height * stride), dtype = numpy.uint8) for y in range (height): idx = y * width * 4 dy = -(y - center_y) for x in range (width): dx = x - center_x dist = dx * dx + dy * dy angle = math.atan2 (dy, dx) if angle < 0: angle += 2 * numpy.pi hue = angle / (2 * numpy.pi) hue_idx = int ((angle + 2 * numpy.pi / 3) / (2 * numpy.pi) * 255) hue_idx = hue_idx % 256 if dist < ((inner - 1) ** 2) * (1 - self.__hist[255 - hue_idx]) or \ dist > ((outer + 1) ** 2): buf[idx + 0] = 0 buf[idx + 1] = 0 buf[idx + 2] = 0 buf[idx + 3] = 0 idx += 4 continue r, g, b = colorsys.hsv_to_rgb (hue, 1.0, 1.0) a = 255 buf[idx + 0] = int (math.floor (r * 255 + 0.5)) buf[idx + 1] = int (math.floor (g * 255 + 0.5)) buf[idx + 2] = int (math.floor (b * 255 + 0.5)) buf[idx + 3] = a idx += 4 source = cairocffi.ImageSurface.create_for_data ( memoryview (buf), cairocffi.FORMAT_ARGB32, width, height, stride ) fg_color = self.get_style_context ().get_color (Gtk.StateFlags.NORMAL) cr.save () cr.set_source_rgba (0, 0, 0, 0) cr.paint () cr.set_source_surface (source, 0, 0) cr.paint () cr.set_line_width (1) cr.new_path () cr.set_source_rgba (*list (fg_color)) cr.arc (center_x, center_y, (self.size - 4) / 2. - self.ring_width, 0, 2 * numpy.pi) cr.stroke () cr.arc (center_x, center_y, (self.size - 2) / 2, 0, 2 * numpy.pi) cr.stroke () cr.arc (center_x, center_y, 5, 0, 2 * numpy.pi) cr.fill () cr.restore ()