def draw_line(x1, y1, x2, y2, color, obj=None, canvas=None, thickness=1): x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) canvas = canvas or obj.widget.canvas token = str(hash(obj)) dx = x2-x1 dy = y2-y1 inc_x = sign(dx) inc_y = sign(dy) dx = abs(dx) dy = abs(dy) if dx >= dy: d = 2*dy - dx delta_a = 2*dy delta_b = 2*dy - 2*dx x, y = (0, 0) for i in range(dx+1-thickness): put_pixel(x1+x, y1+y, color, canvas, token, thickness=thickness) if d > 0: d += delta_b x += inc_x y += inc_y else: d += delta_a x += inc_x else: d = 2*dx - dy delta_a = 2*dx delta_b = 2*dx - 2*dy x, y = (0, 0) for i in range(dy+1-thickness): put_pixel(x1+x, y1+y, color, canvas, token, thickness=thickness) if d > 0: d += delta_b x += inc_x y += inc_y else: d += delta_a y += inc_y
def draw_line_anty_aliasing( x1, y1, x2, y2, color, obj=None, canvas=None, thickness=1 ): canvas = canvas or obj.widget.canvas token = str(hash(obj)) dx = x2-x1 dy = y2-y1 if abs(dx) >= abs(dy): if x1 > x2: draw_line_anty_aliasing( x2, y2, x1, y1, color, obj=obj, canvas=canvas, thickness=thickness ) grad = float(dy)/float(dx) y = y1 for x in range(x1, x2 - thickness): c1, c2 = fpart(y), rfpart(y) put_pixel( x, y, color, canvas, token, alpha=c1, thickness=thickness ) put_pixel( x, y+1, color, canvas, token, alpha=c2, thickness=thickness ) y += grad else: if y1 > y2: draw_line_anty_aliasing( x2, y2, x1, y1, color, obj=obj, canvas=canvas, thickness=thickness ) grad = float(dx)/float(dy) x = x1 for y in range(y1, y2 - thickness): c1, c2 = fpart(x), rfpart(x) put_pixel( x, y, color, canvas, token, alpha=c1, thickness=thickness ) put_pixel( x+1, y, color, canvas, token, alpha=c2, thickness=thickness ) x += grad
def draw_ellipse( x1, y1, x2, y2, color, obj=None, canvas=None, thickness=1 ): if y1 < y2: draw_ellipse( x2, y2, x1, y1, color, obj=obj, canvas=canvas, thickness=thickness ) return canvas = canvas or obj.widget.canvas token = str(hash(obj)) x = (x1 - x2) / 2 + x2 y = (y1 - y2) / 2 + y2 a = (x1 - x2) / 2 b = (y1 - y2) / 2 if (x1 - x2) % 2 == 1: mx = 1 else: mx = 0 if (y1 - y2) % 2 == 1: my = 1 else: my = 0 xc = 0 yc = b aa = a*a aa2 = aa + aa bb = b*b bb2 = bb + bb d = bb - aa + b + (aa/4) dx = 0 dy = aa2 * b while dx < dy: put_pixel(x - xc, y - yc, color, canvas, token, thickness=thickness) put_pixel(x - xc, y + my + yc, color, canvas, token, thickness=thickness) put_pixel(x + mx + xc, y - yc, color, canvas, token, thickness=thickness) put_pixel(x + mx + xc, y + my + yc, color, canvas, token, thickness=thickness) if d > 0: yc -= 1 dy -= aa2 d -= dy xc += 1 dx += bb2 d += bb + dx d += 3*((aa - bb)/2) - (dx + dy)/2 while yc >= 0: put_pixel(x - xc, y - yc, color, canvas, token, thickness=thickness) put_pixel(x - xc, y + my + yc, color, canvas, token, thickness=thickness) put_pixel(x + mx + xc, y - yc, color, canvas, token, thickness=thickness) put_pixel(x + mx + xc, y + my + yc, color, canvas, token, thickness=thickness) if d < 0: xc += 1 dx += bb2 d += bb + dx yc -= 1 dy -= aa2 d += aa - dy
def re_draw_polygon_inside( polygon, texture=None, lights=None, viewer=None, min_x=None, min_y=None, bump_map=None ): clean_polygon_inside(polygon) polygon.token_inside = object() token_obj = polygon.token_inside color = Color(0, 0, 0) canvas = polygon.widget.canvas segments = [ Segment(p1, p2) for p1, p2 in zip(polygon.points[:-1], polygon.points[1:]) ] segments.append(Segment(polygon.points[-1], polygon.points[0])) mini = min(point.y for point in polygon.points) maxi = max(point.y for point in polygon.points) for i in range(mini, maxi): actual_line = Segment(SimplePoint(x=0, y=i), SimplePoint(x=1000, y=i)) intersections = [ Segment.intersection(actual_line, segment) for segment in segments if Segment.is_intersection(actual_line, segment) ] intersections.sort(key=lambda point: point.x, reverse=True) if intersections: for i1, i2 in zip(intersections[::2], intersections[1::2]): if texture and lights and viewer: for j in range(int(i2.x), int(i1.x)): r, g, b = texture.getpixel((j - min_x, i - min_y)) if bump_map: r1, g1, b1 = bump_map.getpixel((j - min_x, i - min_y)) norm = Vec3d(r1/128.0 - 1, g1/128.0 - 1, b1/128.0 - 1) else: norm = None color = Color( float(r)/255 * get_light_phong(j, i, viewer, lights, norm=norm), float(g)/255 * get_light_phong(j, i, viewer, lights, norm=norm), float(b)/255 * get_light_phong(j, i, viewer, lights, norm=norm) ) put_pixel( j, i, color, canvas, str(hash(token_obj)) ) elif texture: for j in range(int(i2.x), int(i1.x)): r, g, b = texture.getpixel((j - min_x, i - min_y)) color = Color(float(r)/255, float(g)/255, float(b)/255) put_pixel( j, i, color, canvas, str(hash(token_obj)) ) elif lights and viewer: for j in range(int(i2.x), int(i1.x)): color = Color( get_light_phong(j, i, viewer, lights), get_light_phong(j, i, viewer, lights), get_light_phong(j, i, viewer, lights) ) put_pixel( j, i, color, canvas, str(hash(token_obj)) ) else: draw_line( int(i1.x), i, int(i2.x), i, color, obj=token_obj, canvas=canvas )
def put_pixel_alphed(x, y, color, canvas, token, alpha, thickness): put_pixel(x, y, color, canvas, token, alpha=1 - alpha, thickness=thickness) put_pixel(x-1, y, color, canvas, token, alpha=alpha, thickness=thickness)
def draw_circle(x1, y1, x2, y2, color, obj=None, canvas=None, thickness=1): canvas = canvas or obj.widget.canvas token = str(hash(obj)) r = length(x1, y1, x2, y2) delta_E = 3 delta_SE = 5 - 2*r d = 1 - r x = 0 y = r put_pixel(x+x1, y+y1, color, canvas, token, thickness=thickness) while y > x: if d < 0: d += delta_E delta_E += 2 delta_SE += 2 else: d += delta_SE delta_E += 2 delta_SE += 4 y -= 1 x += 1 put_pixel(x + x1, y + y1, color, canvas, token, thickness=thickness) put_pixel(y + x1, x + y1, color, canvas, token, thickness=thickness) put_pixel(y + x1, -x + y1, color, canvas, token, thickness=thickness) put_pixel(x + x1, -y + y1, color, canvas, token, thickness=thickness) put_pixel(-x + x1, y + y1, color, canvas, token, thickness=thickness) put_pixel(-y + x1, -x + y1, color, canvas, token, thickness=thickness) put_pixel(-y + x1, x + y1, color, canvas, token, thickness=thickness) put_pixel(-x + x1, -y + y1, color, canvas, token, thickness=thickness)