def vectorize_sector_left(sub_img: ndarray, dwg: Drawing, x: int, y: int, cut_size: int): """Add two triangles to ``dwg`` whose colors are derived from the color averages from the top and bottom diagonals of the 3D BGR image array of the sub image""" b, g, r = upper_tri_sum(sub_img) dwg.add( dwg.polygon([(x, y), (x + cut_size, y), (x + cut_size, y + cut_size)], stroke=svgwrite.rgb(r, g, b, "RGB"), fill=svgwrite.rgb(r, g, b, "RGB"))) b, g, r = lower_tri_sum(sub_img) dwg.add( dwg.polygon([(x, y), (x, y + cut_size), (x + cut_size, y + cut_size)], stroke=svgwrite.rgb(r, g, b, "RGB"), fill=svgwrite.rgb(r, g, b, "RGB")))
def draw_svg(self, drawing: svgwrite.Drawing, g): glane = drawing.g() glane.attribs["class"] = "lane" cp1 = self.control_points[0] cp2 = self.control_points[-1] rel = relative_pose(cp1.as_SE2(), cp2.as_SE2()) _, theta = geo.translation_angle_from_SE2(rel) delta = int(np.sign(theta)) fill = {-1: "#577094", 0: "#709457", 1: "#947057"}[delta] points = self.lane_profile(points_per_segment=10) p = drawing.polygon(points=points, fill=fill, fill_opacity=0.5) glane.add(p) center_points = self.center_line_points(points_per_segment=10) center_points = [ geo.translation_angle_from_SE2(_)[0] for _ in center_points ] p = drawing.polyline( points=center_points, stroke=fill, fill="none", stroke_dasharray="0.02", stroke_width=0.01, ) glane.add(p) g.add(glane) for x in self.control_points: q = x.asmatrix2d().m p1, _ = geo.translation_angle_from_SE2(q) delta_arrow = np.array([self.width / 4, 0]) p2 = SE2_apply_R2(q, delta_arrow) gp = drawing.g() gp.attribs["class"] = "control-point" l = drawing.line( start=p1.tolist(), end=p2.tolist(), stroke="black", stroke_width=self.width / 20.0, ) gp.add(l) c = drawing.circle( center=p1.tolist(), r=self.width / 8, fill="white", stroke="black", stroke_width=self.width / 20.0, ) gp.add(c) g.add(gp)
def plot(self, shape="rect", scale=0, strand=True, **extra): svg = Drawing() g = svg.g() previous = None for feature in self.features: if not previous: previous = feature continue x1, y1 = previous.position x2, y2 = feature.position y1 += (2 + previous.strand) * previous.height + previous.height / 2 y2 += (feature.strand - 1) * feature.height - previous.height / 2 p1 = [x1, y1] p2 = [x1 + previous.length * scale, y1] p3 = [x2 + feature.length * scale, y2] p4 = [x2, y2] if shape == "rect": g.add( svg.polygon(points=[p1, p2, p3, p4], fill=self.color, fill_opacity=0.6)) if shape == "line": g.add( svg.polyline([ ((p1[0] + p2[0]) / 2, y1 - previous.height / 2), ((p1[0] + p2[0]) / 2, y1), ((p3[0] + p4[0]) / 2, y2), ((p3[0] + p4[0]) / 2, y2 + feature.height / 2), ], fill_opacity=0, stroke=self.color, stroke_width=2)) previous = feature return g
def create_svg_image(styles, board_size, hexagons): """ Creates SVG drawing. The drawing contains all given css styles, a board (background rectangle) of given size and all given hexagons. The board can be styled using '.board'. All hexagonal fields can be styled using '.hex-field'. Fields can be also styled using 'hex-field-X', where X is the type of the field. :param styles iterable of css styles (strings) :param board_size tuple representing board size (width, height) :param hexagons iterable of hexagons (tuples in a form of (vertices, type) ) :returns SVG Drawing object """ svg_image = Drawing() for style in styles: svg_image.add(svg_image.style(style)) svg_image.add(svg_image.rect(size=board_size, class_="board")) for hexagon in hexagons: svg_image.add(svg_image.polygon(hexagon.vertices, class_="hex-field hex-field-%d" % hexagon.type)) return svg_image
def LQFP(name, offset, width1, width2, padh, padw, spaceing, padcount, bodyw, edge, pinh, pinw): # document sizes doc = (width1 + 2 * offset[0], width1 + 2 * offset[1]) # basic SVG sheet svg = Drawing(filename=name, size=doc) ####################################################################################################### # PCB Pads ####################################################################################################### pads = svg.g(id="pads") # pins 51 to 75 for n in range(0, padcount): x = offset[0] + ((width1 - width2) / 2) + (n * spaceing) y = offset[1] pad = svg.rect(insert=(x, y), size=(padw, padh), stroke_width=0.05, stroke="black", fill="#D4AA00") pads.add(pad) # pins 1 to 25 for n in range(0, padcount): x = offset[0] + ((width1 - width2) / 2) + (n * spaceing) y = offset[1] + (width1 - padh) pad = svg.rect(insert=(x, y), size=(padw, padh), stroke_width=0.05, stroke="black", fill="#D4AA00") pads.add(pad) # pins 76 to 100 for n in range(0, padcount): x = offset[0] y = offset[1] + ((width1 - width2) / 2) + (n * spaceing) pad = svg.rect(insert=(x, y), size=(padh, padw), stroke_width=0.05, stroke="black", fill="#D4AA00") pads.add(pad) # pins 26 to 50 for n in range(0, padcount): x = offset[0] + (width1 - padh) y = offset[1] + ((width1 - width2) / 2) + (n * spaceing) pad = svg.rect(insert=(x, y), size=(padh, padw), stroke_width=0.05, stroke="black", fill="#D4AA00") pads.add(pad) svg.add(pads) ####################################################################################################### # Part ####################################################################################################### corner = (doc[0] / 2) - (bodyw / 2) part = svg.g(id="part") # pins 51 to 75 for n in range(0, padcount): x = offset[0] + ((width1 - width2) / 2) + ( (padw - pinw) / 2) + (n * spaceing) y = corner - pinh pad = svg.rect(insert=(x, y), size=(pinw, pinh), stroke_width=0.05, stroke="black", fill="#999999") part.add(pad) # pins 1 to 25 for n in range(0, padcount): x = offset[0] + ((width1 - width2) / 2) + ( (padw - pinw) / 2) + (n * spaceing) y = corner + bodyw pad = svg.rect(insert=(x, y), size=(pinw, pinh), stroke_width=0.05, stroke="black", fill="#999999") part.add(pad) # pins 76 to 100 for n in range(0, padcount): x = corner - pinh y = offset[0] + ((width1 - width2) / 2) + ( (padw - pinw) / 2) + (n * spaceing) pad = svg.rect(insert=(x, y), size=(pinh, pinw), stroke_width=0.05, stroke="black", fill="#999999") part.add(pad) # pins 26 to 50 for n in range(0, padcount): x = corner + bodyw y = offset[0] + ((width1 - width2) / 2) + ( (padw - pinw) / 2) + (n * spaceing) pad = svg.rect(insert=(x, y), size=(pinh, pinw), stroke_width=0.05, stroke="black", fill="#999999") part.add(pad) # plastic body points = [(corner, corner + edge), (corner + edge, corner), (corner + bodyw - edge, corner), (corner + bodyw, corner + edge), (corner + bodyw, corner + bodyw - edge), (corner + bodyw - edge, corner + bodyw), (corner + edge, corner + bodyw), (corner, corner + bodyw - edge)] body = svg.polygon(points=points, stroke_width=0.05, stroke="black", fill="#333333") part.add(body) # pin 1 indicator ind = svg.circle(center=(corner + 1, corner + bodyw - 1), r=0.5, stroke_width=0.05, stroke="black", fill="#333333") part.add(ind) svg.add(part) svg.save()
def plot(self, shape="arrow", strand=True, scale=1 / 2000, **extra): height = self.height if strand: y1 = self.frag_genome.position[ 1] - height / 2.0 - self.strand * height y2 = y1 + height else: y1 = self.frag_genome.position[1] - height / 2.0 y2 = self.frag_genome.position[1] + height / 2.0 if shape == "rect": p1 = [ self.frag_genome.position[0] + (self.start - self.frag_genome.start) * scale, y1 ] p2 = [ self.frag_genome.position[0] + (self.end - self.frag_genome.start) * scale, y1 ] p3 = [ self.frag_genome.position[0] + (self.end - self.frag_genome.start) * scale, (y1 + y2) / 2 ] p4 = [ self.frag_genome.position[0] + (self.end - self.frag_genome.start) * scale, y2 ] p5 = [ self.frag_genome.position[0] + (self.start - self.frag_genome.start) * scale, y2 ] if shape == "arrow": if self.strand == 1: p1 = [ self.frag_genome.position[0] + (self.start - self.frag_genome.start) * scale, y1 ] p2 = [ self.frag_genome.position[0] + (self.end - self.frag_genome.start) * scale - height / 3, y1 ] p3 = [ self.frag_genome.position[0] + (self.end - self.frag_genome.start) * scale, (y1 + y2) / 2 ] p4 = [ self.frag_genome.position[0] + (self.end - self.frag_genome.start) * scale - height / 3, y2 ] p5 = [ self.frag_genome.position[0] + (self.start - self.frag_genome.start) * scale, y2 ] else: p1 = [ self.frag_genome.position[0] + (self.end - self.frag_genome.start) * scale, y1 ] p2 = [ self.frag_genome.position[0] + (self.start - self.frag_genome.start) * scale + height / 3, y1 ] p3 = [ self.frag_genome.position[0] + (self.start - self.frag_genome.start) * scale, (y1 + y2) / 2 ] p4 = [ self.frag_genome.position[0] + (self.start - self.frag_genome.start) * scale + height / 3, y2 ] p5 = [ self.frag_genome.position[0] + (self.end - self.frag_genome.start) * scale, y2 ] if self.strand * p2[0] < self.strand * p1[0]: p2 = p1 p4 = p5 self.position = p1 if self.strand == -1: self.position = p3 svg = Drawing() if self.parent["Homology"]: patch = svg.polygon(points=[p1, p2, p3, p4, p5], fill=self.parent["Homology"].color) else: patch = svg.polygon(points=[p1, p2, p3, p4, p5], fill="white", stroke="black") t = [(p1[0] + p3[0]) / 2, p1[1] - 1] a = 1 if strand and self.strand == -1: t = [(p1[0] + p3[0]) / 2, p5[1] + 5] a = -1 text = svg.text(text=self.name, insert=t, font_size="8", transform='rotate(%s, %s, %s)' % (-45 * a, t[0], t[1])) return patch, text
def diode_svg_frame(illuminated, num_across=9, num_down=8, frame=0, single_route=-1): filename = "diode{:03d}.svg".format(frame) led_symbol = "resources/Symbol_LED.svg" image_width = 600 image_height = 400 right_margin = 30 bottom_margin = 30 dwg = Drawing(filename, size=(image_width+right_margin, image_height+bottom_margin), style="background-color:white") # create a white background rectangle dwg.add(dwg.rect(size=(image_width+right_margin, image_height+bottom_margin), insert=(0, 0), fill="white")) LED_dimensions = [106.0, 71.0] LED_points = [[35, 68], [35, 31], [66, 50]] LED_entries = [[4, 50], [103, 50]] aspect_ratio = LED_dimensions[1]/LED_dimensions[0] new_width = image_width/num_across new_height = new_width*aspect_ratio LED_scale = 0.75 LED_offsets = [new_width*LED_scale/2, new_height*LED_scale] junction_radius = 0.8 elements = [] for i in range(0, num_across): x_pos = new_width*(num_across-i-1) if illuminated[1] >= illuminated[0]: incoming_wire = illuminated[1] + 1 else: incoming_wire = illuminated[1] if i == incoming_wire: connection = "+" text_fill = "red" elif i == illuminated[0]: connection = "-" text_fill = "black" else: connection = "NC" text_fill = "gray" wire_label = "{} {}".format(i+1, connection) # the input wire title dwg.add(dwg.text(wire_label, insert=(x_pos+new_width-10, 10), fill=text_fill)) for j in range(0, num_down): y_pos = (image_height/num_down)*j position = [x_pos+LED_offsets[0], y_pos+LED_offsets[1]] scale = [LED_scale*new_width/LED_dimensions[0], LED_scale*new_height/LED_dimensions[1]] # the led svg dwg.add(dwg.image(led_symbol, insert=position, size=(new_width*LED_scale, new_height*LED_scale))) if i == illuminated[0] and j == illuminated[1] and single_route == -1: points = [] for point in LED_points: points.append(transform_point(point, scale, position)) # the illuminated svg box dwg.add(dwg.polygon(points=points, fill="yellow")) line_fill = "green" stroke_width = 1 insert_pos = -1 else: line_fill = "black" insert_pos = 0 stroke_width = 0.5 # for each LED, we want to generate a line going from the input # to its output entry_point = transform_point(LED_entries[0], scale, position) if i > j: incoming_line_points = [[new_width*(num_across-j)-LED_offsets[0], 0], [new_width*(num_across-j)-LED_offsets[0], y_pos+20], [entry_point[0], y_pos+20], entry_point] elif j > i: incoming_line_points = [ [new_width * (num_across - j - 1) - LED_offsets[0], 0], [new_width * (num_across - j - 1) - LED_offsets[0], entry_point[1] + LED_offsets[1]], [entry_point[0], entry_point[1]+LED_offsets[1]], entry_point] elif i == j: incoming_line_points = [ [new_width * (num_across - j - 1) - LED_offsets[0], 0], [new_width * (num_across - j - 1) - LED_offsets[0], entry_point[1]], entry_point] else: incoming_line_points = [] elements.insert(insert_pos, make_junction_line(dwg, incoming_line_points, junction_radius, line_fill, stroke_width)) # outgoing line exit_point = transform_point(LED_entries[1], scale, position) outgoing_line_points = [exit_point, [x_pos+new_width-LED_offsets[0], exit_point[1]], [x_pos+new_width-LED_offsets[0], 0]] elements.insert(insert_pos, make_junction_line(dwg, outgoing_line_points, junction_radius, line_fill, stroke_width)) route_points = [[new_width * (num_across - j - 1) - LED_offsets[0], 0]] for point in range(0, single_route+1): if point < i: route_points.append([new_width * (num_across - j - 1) - LED_offsets[0], 0]) # now create the network nodes = [] for i in range(0, num_across): for j in range(0, num_down): nodes.append(entry_point) nodes.append(exit_point) # flatten the elements structure elements = sum(elements, []) print(elements) # the lines should be drawn last so that they are layered on top of all # other elements #for element in elements: # dwg.add(element) dwg.save() return convert(image_width, filename)
def _create_group(self, drawing: Drawing, projection: np.ndarray, viewport: Viewport, group: Group): """ Render all the meshes contained in this group. The main consideration here is that we will consider the z-index of every object in this group. """ default_style = group.style or {} shaders = [ mesh.shader or (lambda face_index, winding: {}) for mesh in group.meshes ] annotators = [ mesh.annotator or (lambda face_index: None) for mesh in group.meshes ] # A combination of mesh and face indes mesh_faces: List[np.ndarray] = [] for i, mesh in enumerate(group.meshes): faces = mesh.faces # Extend each point to a vec4, then transform to clip space. faces = np.dstack([faces, np.ones(faces.shape[:2])]) faces = np.dot(faces, projection) # Reject trivially clipped polygons. xyz, w = faces[:, :, :3], faces[:, :, 3:] accepted = np.logical_and(np.greater(xyz, -w), np.less(xyz, +w)) accepted = np.all(accepted, 2) # vert is accepted if xyz are all inside accepted = np.any(accepted, 1) # face is accepted if any vert is inside degenerate = np.less_equal(w, 0)[:, :, 0] # vert is bad if its w <= 0 degenerate = np.any(degenerate, 1) # face is bad if any of its verts are bad accepted = np.logical_and(accepted, np.logical_not(degenerate)) faces = np.compress(accepted, faces, axis=0) # Apply perspective transformation. xyz, w = faces[:, :, :3], faces[:, :, 3:] faces = xyz / w mesh_faces.append(faces) # Sort faces from back to front. mesh_face_indices = self._sort_back_to_front(mesh_faces) # Apply viewport transform to X and Y. for faces in mesh_faces: faces[:, :, 0:1] = (1.0 + faces[:, :, 0:1]) * viewport.width / 2 faces[:, :, 1:2] = (1.0 - faces[:, :, 1:2]) * viewport.height / 2 faces[:, :, 0:1] += viewport.minx faces[:, :, 1:2] += viewport.miny # Compute the winding direction of each polygon. mesh_windings: List[np.ndarray] = [] for faces in mesh_faces: windings = np.zeros(faces.shape[0]) if faces.shape[1] >= 3: p0, p1, p2 = faces[:, 0, :], faces[:, 1, :], faces[:, 2, :] normals = np.cross(p2 - p0, p1 - p0) np.copyto(windings, normals[:, 2]) mesh_windings.append(windings) group_ = drawing.g(**default_style) text_group_ = drawing.g(**default_style) # Finally draw the group for mesh_index, face_index in mesh_face_indices: face = mesh_faces[mesh_index][face_index] style = shaders[mesh_index](face_index, mesh_windings[mesh_index][face_index]) if style is None: continue face = np.around(face[:, :2], self.precision) if len(face) == 1: group_.add( drawing.circle(face[0], style.pop("radius", 0.005), **style)) if len(face) == 2: group_.add(drawing.line(face[0], face[1], **style)) else: group_.add(drawing.polygon(face, **style)) annotation = annotators[mesh_index](face_index) if annotation is not None: centroid = face.mean(axis=0) text_group_.add(drawing.text(insert=centroid, **annotation)) return [group_, text_group_]