def _write(self, shapes, svg_file, args): stroke_width = args.stroke_width if args.stroke_width else "0.1%" write_preamble(args, svg_file) shift = Vector2D(args.width / 2.0, args.height / 2.0) for points, polygon in shapes: rgb = self.parts.colours.get(polygon.colour, "#ffffff") stroke_colour = args.stroke_colour if args.stroke_colour else rgb context = dict(rgb=rgb, stroke_width=stroke_width, stroke_colour=stroke_colour, opacity=self._opacity_from_colour(polygon.colour)) if len(points) == 2: context['point1'] = Vector2D(points[0].x, -points[0].y) + shift context['point2'] = Vector2D(points[1].x, -points[1].y) + shift svg_file.write(SVG_LINE.format(**context)) else: svg_file.write(SVG_POLYGON_PREAMBLE.format(**context)) for point in points: dpoint = Vector2D(point.x, -point.y) + shift svg_file.write('{point.x:.6f},{point.y:.6f} '.format(point=dpoint)) svg_file.write('" />\n') svg_file.write("</svg>\n") svg_file.close()
def _project_polygons(width, height, polygons): # vx' = width + az # vy' = height + bz pixel_x = 0.5 pixel_y = 0.5 half_width = width / 2.0 half_height = height / 2.0 new_polygons = [] for polygon in polygons: new_points = [] for point in polygon.points: point_x = half_width * (point.x / (half_width + pixel_x * -point.z)) point_y = half_height * (point.y / (half_height + pixel_y * -point.z)) new_point = Vector2D(point_x, point_y) new_points.append(new_point) new_polygons.append((new_points, polygon)) return new_polygons
def project_polygons(width, height, polygons): # vx' = width + az # vy' = height + bz print(len(polygons)) pixel_x = 0.5 pixel_y = 0.5 half_width = width / 2.0 half_height = height / 2.0 new_polygons = [] for polygon in polygons: new_points = [] for point in polygon: point_x = half_width * (point["x"] / (half_width + pixel_x * -point["z"])) point_y = half_height * (point["y"] / (half_height + pixel_y * -point["z"])) new_point = Vector2D(point_x, point_y) new_points.append(new_point) new_polygons.append((new_points, polygon)) return new_polygons
def render(self, image, depth, viewport_scale, stroke_colour): """ Sort the edges of the polygon by their minimum projected y coordinates, discarding horizontal edges. """ edges = self.get_edges(image, viewport_scale) if not edges: return width, height = image.size end_py = edges[-1].point2.y if end_py < 0: return edge1 = edges.pop(0) if edge1.point1.y >= height: return edge2 = edges.pop(0) int_edge1_y1 = int(edge1.point1.y) if int_edge1_y1 < edge1.point1.y or int_edge1_y1 < edge2.point1.y: int_edge1_y1 += 1 while int_edge1_y1 <= end_py and int_edge1_y1 < height: # Retrieve new edges as required. if int_edge1_y1 >= edge1.point2.y: if not edges: break edge1 = edges.pop(0) if int_edge1_y1 >= edge2.point2.y: if not edges: break edge2 = edges.pop(0) if int_edge1_y1 < 0: int_edge1_y1 += 1 continue # Calculate the starting and finishing coordinates of the span # at the current y coordinate. gradient_1 = Vector2D(edge1.dx_dy, edge1.dz_dy) start_point_1 = Vector2D(edge1.point1.x, edge1.point1.z) start_1 = start_point_1 + (int_edge1_y1 - edge1.point1.y) * gradient_1 gradient_2 = Vector2D(edge2.dx_dy, edge2.dz_dy) start_point_2 = Vector2D(edge2.point1.x, edge2.point1.z) start_2 = start_point_2 + (int_edge1_y1 - edge2.point1.y) * gradient_2 # Do not render the span if it lies outside the image or has # values that cannot be stored in the depth buffer. # Truncate the span if it lies partially within the image. if start_1.x > start_2.x: start_2, start_1 = start_1, start_2 # Only calculate a depth gradient for the span if it is more than # one pixel wide. if start_1.y <= 0 and start_2.y <= 0: int_edge1_y1 += 1 continue elif start_1.y >= Z_MAX and start_2.y >= Z_MAX: int_edge1_y1 += 1 continue start_x, end_sx = int(start_1.x), int(start_2.x) if start_x < start_1.x: start_x += 1 if start_x >= width: int_edge1_y1 += 1 continue elif end_sx < 0: int_edge1_y1 += 1 continue int_edge1_y1 = self.draw_span(depth, end_sx, image, int_edge1_y1, start_1, start_2, start_x, stroke_colour, width)