# drawshapes.py
# written by Jeffrey Kleykamp
import math
import pygame
TAU = 2 * math.pi
def getpolygon(origin, radius, N, start=0, end=None):
out = []
x, y = origin
Nf = float(N)
if end is None:
end = TAU
for i in range(N):
xp = x + radius * math.sin(end * i / Nf + start)
yp = y - radius * math.cos(end * i / Nf + start)
out.append((xp, yp))
return out
def regpolygon(surf, color, origin, radius, width, N, start=0):
if width == 0 or width >= radius:
pl = getpolygon(origin, radius, N)
r = pygame.draw.polygon(surf, color, pl)
return r
else:
end = TAU * (N+1) / float(N)
p1 = getpolygon(origin, radius, N+1, start=start, end=end)
p2 = getpolygon(origin, radius-width, N+1, start=start, end=end)
p2.reverse()
p1.extend(p2)
r = pygame.draw.polygon(surf, color, p1)
return r
def circle(surf, color, origin, radius, width=0, N=64):
regpolygon(surf, color, origin, radius, width, N, 0)
def arc(surf, color, origin, radius, start=0, end=None, width=0, N=64):
if width == 0 or width >= radius * 0.5:
p2 = [origin]
else:
p2 = getpolygon(origin, radius-width, N, start=start, end=end)
p2.reverse()
p1 = getpolygon(origin, radius, N, start=start, end=end)
p1.extend(p2)
r = pygame.draw.polygon(surf, color, p1)
return r
def wedge(surf, color, origin, radius, start=0, end=None, width=0, N=64):
if width == 0 or width >= radius * 0.5:
return arc(surf, color, origin, radius, start=start, end=end, width=0, N=N)
# does outside polygon
p1 = [origin]
p2 = getpolygon(origin, radius, N, start=start, end=end)
p3 = [origin]
p1.extend(p2)
p1.extend(p3)
# does inside polygon
x, y = origin
xp = x + width * math.sin(end * 0.5 + start)
yp = y - width * math.cos(end * 0.5 + start)
norigin = (xp,yp)
p3 = [norigin]
p2 = getpolygon(norigin, radius-2*width, N, start=start, end=end)
p2.reverse()
p1.extend(p3)
p1.extend(p2)
p1.extend(p3)
# draws the full polygon
r = pygame.draw.polygon(surf, color, p1)
return r
def ellipse(surf, color, rect, width=0, N=64):
# draws an ellipse that bounds the rect
xradius = rect.width * 0.5
yradius = rect.height * 0.5
origin = rect.center
return ellipse_radius(surf, color, origin, xradius, yradius, width=width, N=N)
def ellipse_radius(surf, color, origin, xradius, yradius, width=0, N=64):
# draws an ellipse that has the two radii
pl = []
x, y = origin
if width >= min(xradius, yradius):
width = 0
if width is 0:
end = TAU
else:
end = TAU * (N+1) / float(N)
N = N+1
Nf = float(N)
for i in range(N):
xp = x + xradius * math.sin(end * i / Nf)
yp = y - yradius * math.cos(end * i / Nf)
pl.append((xp, yp))
if width is not 0:
xradius -= width
yradius -= width
for i in range(N):
xp = x + xradius * math.sin(-end * i / Nf)
yp = y - yradius * math.cos(-end * i / Nf)
pl.append((xp, yp))
r = pygame.draw.polygon(surf, color, pl)
return r
if __name__ == '__main__':
# test code
import os
# this code trys to incorporate aa lines but it's not as good as polygon alone
# because it doesn't fill in the polygon. So I tried doing both...
old = pygame.draw.polygon
def idk(s,c,pl):
pygame.draw.aalines(s,c,True,pl,False)
old(s,c,pl)
def switchxray():
pygame.draw.polygon = lambda s,c,pl: pygame.draw.aalines(s,c,True,pl,False)
def switchfull():
pygame.draw.polygon = idk
def switchori():
pygame.draw.polygon = old
def draw_3modes(i, j,dx,f):
pos = (dx*i, j*dx)
f(pos)
i += 2
switchfull()
pos = (dx*i, j*dx)
f(pos)
i += 2
switchxray()
pos = (dx*i, j*dx)
f(pos)
i += 2
switchori()
def test():
print("The first col uses the current draw function")
print("The next col uses polygons")
print("The next col uses polygons + aalines")
print("The next col uses aalines only")
print("Ideally aalines should fill leading to smooth shapes")
input("Press enter to continue")
width = 800
height = 600
os.environ['SDL_VIDEO_CENTERED'] = '1'
screen = pygame.display.set_mode((width,height))
c = pygame.color.Color("blueviolet")
radius = 75
width = 25
dx = radius + 10
r = pygame.Rect(0,0,2*radius,2*radius)
# draws a bunch of circles
pygame.draw.circle(screen, c, (dx, dx), radius, width)
f = lambda p: circle(screen, c, p, radius, width)
draw_3modes(3,1,dx,f)
# draws a bunch of arcs
r.center = (dx, 3*dx)
pygame.draw.arc(screen, c, r, math.pi/2, 3, width)
f = lambda p: arc(screen, c, p, radius, 0, math.pi/2-3, width)
draw_3modes(3,3,dx,f)
# draws a bunch of circles nearly filled in
pygame.draw.circle(screen, c, (dx, 4*dx), radius, radius - 5)
f = lambda p: circle(screen, c, p, radius, radius - 5)
draw_3modes(3,4,dx,f)
# draws a bunch of ellipses
r = pygame.Rect(0,0,1.5*radius,2*radius)
r.center = (dx, 6*dx)
pygame.draw.ellipse(screen, c, r, width)
f = lambda p: ellipse_radius(screen, c, p, 3*radius/4.0, radius, width)
draw_3modes(3,6,dx,f)
pygame.display.flip()
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT or (e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE):
pygame.quit()
return
test()
Attachment:
drawpatch.png
Description: PNG image