import turtle
class GeometricObject:
def __init__(self):
self.line_color = 'black'
def get_color(self):
return self.line_color
def set_color(self, c):
self.line_color = c
# A point is a geometric object, so we derive from it
class Point(GeometricObject):
def __init__(self, x, y):
super().__init__()
self.x = x
self.y = y
def draw(self):
turtle.goto(self.x, self.y)
turtle.dot(1, self.get_color())
# A polygon is a geometric object, so we derive from it
class Polygon(GeometricObject):
def __init__(self):
super().__init__()
# For a polygon, we store it as a list of points initially empty
self.points = []
def add_point(self, p):
self.points.append(p)
def draw(self):
if len(self.points) == 0:
return
turtle.color(self.get_color())
for p in self.points:
turtle.goto(p[0], p[1])
turtle.down()
# Go back to the start
turtle.goto(self.points[0][0], self.points[1][1])
turtle.up()
# A rectangle is a polygon, so we derive from it
class Rectangle(Polygon):
def __init__(self, x, y, width, height):
super().__init__()
self.add_point( (x, y) )
self.add_point( (x + width, y) )
self.add_point( (x + width, y + height) )
self.add_point( (x, y + height) )
# The add_point method causes a "Circle-ellipse problem" and therefore violates
# the Liskov substitution principle, since it does not make sense to add a point
# to a rectangle.
# A canvas has many geometric objects, so we store them in a property
class Canvas:
def __init__(self):
self.geo = []
def add(self, obj):
self.geo.append(obj)
def draw(self):
for g in self.geo:
g.draw()
turtle.setworldcoordinates(-5, -5, 5, 5)
turtle.up()
canvas = Canvas()
canvas.add(Rectangle(1, 2, 0.5, 0.7))
canvas.add(Point(-1, -3))
r = Rectangle(-1, 4, 2, 1)
r.set_color("green")
canvas.add(r)
canvas.draw()
input("Press enter")
Each class in python is itself an object with information about the methods and base classes. The super function (used above) allows access to this information and in partiuclar allows you to call methods that are defined on your base class. I used it above to call the __init__
method on the superclass or parent class, so inside Point
initialization, I call the geometric object initialization method as the first step.
Add a class Square
which derives from Rectangle
and whose initialization method takes three parameters, the x,y location and the side length. Call the Rectangle initialization method using super
.
RightTriangle
which derives from Polygon
and whose initialization method takes four parameters:
left_x
,left_y
location of the lower left corner of the triangle, which will be the right anglebase
: the length of the base of the triangle, extending from left_x,left_y
to the right horizontally.alpha
: the angle in radians between the base and the hypotenuse. |\
| \
| \
| \
| \
| \
| \
| \
| α \
(x, y) -> ----------
base
You will need to use the math module trig functions to compute the top corner inside the initialization method: remember that the math module uses radians and pi is available at math.pi
.