Lab 5
You cannot submit for this problem because the homework's deadline is due.
EECS 280 Lab 05: Inheritance and Subtype Polymorphism
Lab Due Friday, June 7, 2024, 11:59 pm
In this lab, we will use a set of Abstract Data Types (ADTs) to write
an ASCII art drawing program. We've provided a Canvas ADT that manages
an image (i.e. a grid of "pixels") and you will finish a hierarchy
that represents the shapes that may be drawn. Additionally, we've
prepared an Exam Prep that reviews similar topics. Finally, we've
included some optional exam-style practice problems to study for the
exam.
You may work alone or with a partner. Please see the syllabus for
partnership rules.
Submit the code files below on the autograder. We encourage you to
complete the lab Exam Prep, but it is not turned in for credit.
Files to submit
shapes.h
shapes.cpp
lab05.cpp
Canvas.cpp
Completion Criteria/Checklist:
To pass this lab, you must finish tasks 1 and 2.
Declare a derived class
Circle
fromEllipse
in
shapes.h
and implement the necessary functions inside of
shapes.cpp
. Don't override any member functions.Declare a derived class
Rectangle
fromShape
in
shapes.h
and implement the necessary functions inside of
shapes.cpp
. Override botharea
anddraw
.
Lab Exercises
The Files
Here's a summary of this lab's files.
File | Description |
---|---|
Canvas.h |
Declaration of the Canvas ADT. |
Canvas.cpp |
Implementations of the member functions for Canvas . |
lab05.cpp |
Includes the main function, which draws some shapes. |
shapes.h |
Declaration of the Shape class and its derived classes. |
shapes.cpp |
Implementations of Shape and its derived classes. |
Testing Code
The main
function in lab05.cpp
creates an Ellipse
, a Circle
,
and a Rectangle
and stores pointers to them in a shapes
array to
draw them to a Canvas. Some parts are commented out to ensure the
starter code compiles. You may comment things in/out as you work on
different tasks.
The starter code should compile successfully without any modifications, so make sure you are able to compile and run it with the following commands. The code may be missing some pieces, contain some bugs, or crash when you run it, but you'll fix each throughout the course of the lab.
$ g++ -Wall -Werror -g -pedantic --std=c++17 Canvas.cpp shapes.cpp lab05.cpp -o lab05.exe
$ ./lab05.exe
Introduction
You should first familiarize yourself with the ADTs we will use in
this lab. They are described briefly below and in the comments in
Canvas.h
and shapes.h
. As with any good ADT, you shouldn't need to
look at the implementations to know what they do and how to use them.
Canvas
A Canvas
represents a 2D image and supports these operations.
void set_pixel(int x, int y, bool value)
Sets a pixel in the
Canvas
to ON (true) or OFF (false). Initially,
all pixels are set to OFF.void print() const
Prints out the image in the
Canvas
to the terminal.
Shape
A Shape
is an abstract base class that represents a geometric shape.
It declares the two pure virtual functions area
and draw
, which
means that each derived class must implement both functions according
to the shape they represent. Furthermore, since they are virtual, when
we use a pointer to Shape
, the appropriate implementation for that
shape will be used.
Note: Since the functions are pure virtual, we cannot instantiate
a Shape
object. However, we will be able to instantiate derived
classes of Shape
that provide implementations of these functions.
Ellipse
An Ellipse
is an example of a derived type, which inherits from
Shape
. It is defined by x and y radii as shown in the picture. You
can see that both area
and draw
are overridden from Shape
, to
work for an Ellipse
.
Drawing on a Canvas
In order to draw the Ellipse
, we check every pixel in the Canvas
and we turn it ON if it is contained inside the shape. To determine
whether a pixel is inside, we use the equation for an ellipse based on
its x/y position and radii (don't worry, you don't need to know this
formula, since the shapes you're asked to implement are simpler).
Note: In the draw
implementation, why are we able to access the
x_rad
and y_rad
member variables directly, but we need to use the
getters for x_pos
and y_pos
?
Task 1 - Circle
Start by writing Circle
. Here are some things to consider:
- Separate your code into
shapes.h
andshapes.cpp
appropriately. Circle
should be derived fromEllipse
(which itself is derived fromShape
).- The constructor should take in a single
double
for itsradius
. - Remember that a
Circle
is just a special case of anEllipse
.
Note: You shouldn't need to create any private variables or
override any functions.
In order to try your new shape, start by uncommenting the relevant
code inside lab05.cpp
. Now, you will need to increase SIZE
and add
the new shape to the shapes
array.
Task 2 - Rectangle
Next we will write Rectangle
. Again, here are some things to
consider:
- Separate your code into
shapes.h
andshapes.cpp
appropriately. Rectangle
should be derived directly fromShape
.- The constructor should take in two
double
s for itswidth
andheight
, respectively. - You need to declare additional member variables to store the
width
andheight
. - You need to override both
area
anddraw
, because they are pure virtual inShape
. - For
draw
, follow the same structure used inEllipse
: check every pixel in theCanvas
and turn it ON if it is contained inside the shape. - Remember that a rectangle at \[ \left( x_{pos}, y_{pos} \right) \] contains the point \[ \left( x, y \right) \] if and only if \[ \left| x - x_{pos} \right| \leq \frac{width}{2} \] and \[ \left| y - y_{pos} \right| \leq \frac{height}{2} \]
Note: You may find the abs
function helpful to obtain the
absolute value of a number.
Now uncomment the relevant code in lab05.cpp
and add rect
to the
shapes
array. Since the array is now holding shapes other than
Ellipse
s you will also need to change the type of the array to hold
Shape
pointers.
Submit
Submit all files to the autograder.