def render(self, size: Tuple[int, int] = (512, 512), view_box: str = "-0.5 -0.5 1.0 1.0", **extra) -> Drawing: drawing = Drawing("", size, viewBox=view_box, **extra) for view in self.views: projection = np.dot(view.camera.view, view.camera.projection) clip_path = drawing.defs.add(drawing.clipPath()) clip_min = view.viewport.minx, view.viewport.miny clip_size = view.viewport.width, view.viewport.height clip_path.add(drawing.rect(clip_min, clip_size)) # TODO: Handle Z-index with meshes for group in view.scene.groups: for g in self._create_group(drawing, projection, view.viewport, group): g["clip-path"] = clip_path.get_funciri() drawing.add(g) return drawing
def draw_path_clip(self): path_filename = "{}/path_clip_{}.svg".format( self.output_folder, basename(self.filename).replace(".svg", "")) dwg = Drawing(path_filename) image_bbox = calc_overall_bbox(self.tile_paths) dx = self.pent_x - min(image_bbox[0], image_bbox[1]) dy = self.pent_y - min(image_bbox[2], image_bbox[3]) dwg.add( dwg.path( **{ "d": self.new_pentagon().d(), "fill": "none", 'stroke-width': 4, 'stroke': rgb(0, 0, 0) })) neg_transform = "translate({}, {})".format(-dx, -dy) transform = "translate({}, {})".format(dx, dy) clip_path = dwg.defs.add( dwg.clipPath(id="pent_path", transform=neg_transform)) clip_path.add(dwg.path(d=self.new_pentagon().d())) group = dwg.add( dwg.g(clip_path="url(#pent_path)", transform=transform, id="clippedpath")) for i, path in enumerate(self.tile_paths): group.add( dwg.path(d=path.d(), style=self.tile_attributes[i].get('style'), id=self.tile_attributes[i]['id'])) dwg.add(dwg.use("#clippedpath", transform="transform(100, 100)")) dwg.viewbox(self.pent_x, self.pent_y, self.pent_width, self.pent_height) dwg.save() xml = xml.dom.minidom.parse(path_filename) open(path_filename, "w").write(xml.toprettyxml())
def render(self, dwg: Drawing) -> Group: g = dwg.g() # Render antennae antennae_rho = self.size * self.antennae_rho antennae_base_phi = 1.5 * math.pi antennae_delta_phi = 0.2 * math.pi antennae_delta_phi_total = (self.antennae_count - 1) * antennae_delta_phi antennae_left_phi = antennae_base_phi - antennae_delta_phi_total / 2 for i in range(self.antennae_count): antennae_coords = ( antennae_rho * math.cos(antennae_left_phi + i * antennae_delta_phi), antennae_rho * math.sin(antennae_left_phi + i * antennae_delta_phi)) antenna = dwg.circle(center=antennae_coords, r=self.size * self.antennae_relative_size, fill=self.color) path = dwg.path(stroke=helper.colors.darken_hex(self.color), stroke_width=3) path.push("M %f %f" % antennae_coords) path.push("L %f %f" % (0, 0)) g.add(path) g.add(antenna) # Render body shadow_mask = dwg.defs.add(dwg.clipPath(id="bodymask-%s" % self.id)) shadow_mask.add(dwg.circle(center=(0, 0), r=self.size)) body_dark = dwg.circle(center=(0, 0), r=self.size, stroke_width=0, fill=helper.colors.darken_hex(self.color), clip_path="url(#bodymask-%s)" % self.id) g.add(body_dark) body_highlight = dwg.circle(center=(-self.size * .2, -self.size * .2), r=self.size * .95, stroke_width=0, fill=self.color, clip_path="url(#bodymask-%s)" % self.id) g.add(body_highlight) # Render eyes eye_rho = self.size * self.eye_distance eye_base_phi = 1.5 * math.pi eye_delta_phi = 0.3 * math.pi eye_delta_phi_total = (self.eye_count - 1) * eye_delta_phi eye_left_phi = eye_base_phi - eye_delta_phi_total / 2 for eye_i in range(self.eye_count): eye_coords = (eye_rho * math.cos(eye_left_phi + eye_i * eye_delta_phi), eye_rho * math.sin(eye_left_phi + eye_i * eye_delta_phi)) eye = self.eye_factory(self.size * self.eye_relative_size) eye_g = eye.render(dwg) eye_g.translate(eye_coords[0], eye_coords[1]) g.add(eye_g) # Render mouth mouth = self.mouth_factory(self.size * self.mouth_relative_size, helper.colors.darken_hex(self.color, .75)) mouth_g = mouth.render(dwg) mouth_g.translate(0, self.size * self.mouth_height) g.add(mouth_g) return g
def draw_pattern(self): self.output_filename = "{}/snake_tiling_m_{}_{}.svg".format( self.output_folder, self.dx, self.dy) dwg = Drawing(self.output_filename) # add background panel background_clippath = dwg.rect(insert=(self.pattern_viewbox[0], self.pattern_viewbox[1]), size=('100%', '100%')) background_panel = dwg.rect(insert=(self.pattern_viewbox[0], self.pattern_viewbox[1]), size=('101%', '101%'), fill='#3072a2') clip_path = dwg.defs.add(dwg.clipPath(id="background_panel")) clip_path.add(background_clippath) clipped_drawing = dwg.add( dwg.g(clip_path="url(#background_panel)", id="clippedpath")) clipped_drawing.add(background_panel) current_color = 0 def add_pentagon(group, transform, current_color, draw_pent=True): pent_group = group.add( dwg.g(transform=format_transform(*transform))) if draw_pent: pent_group.add( dwg.path( **{ 'd': self.new_pentagon().d(), 'fill': self.colors[current_color % len(self.colors)], 'stroke-width': 4, 'stroke': rgb(0, 0, 0) })) return pent_group for y in range(self.num_down): transform = "translate({}, {})".format(0, self.rep_spacing * y) dgroup = clipped_drawing.add(dwg.g(transform=transform)) for x in range(self.num_across): # if x is odd, point 1 of pent 1 needs to be attached to point 3 of pent 2 if x % 2 == 1: dx = int( x / 2 ) * self.rep_spacing + self.pent_width * 2 + self.column_offset.real diff = dx + self.column_offset.imag * 1j else: diff = int(x / 2) * self.rep_spacing for i in range(4): snake_bbox = calc_overall_bbox(self.tile_paths) snake_width, snake_height = abs(snake_bbox[0] - snake_bbox[1]), \ abs(snake_bbox[2] - snake_bbox[3]) pent_group = add_pentagon( dgroup, (self.transforms[i][0], self.transforms[i][1] + diff), current_color, draw_pent=False) for i, path in enumerate(self.tile_paths): stransform = 'translate({},{})'.format( snake_width * self.dx, snake_height * self.dy) pent_group.add( dwg.path( **{ 'd': path.d(), 'style': self.tile_attributes[i].get( 'style'), 'id': self.tile_attributes[i]['id'], 'transform': stransform })) current_color += 1 dwg.viewbox(*self.pattern_viewbox) dwg.save()