# EECS 280 Lab 05: Inheritance and Subtype Polymorphism

### Lab Due Sunday, October 18, 2020, 8:00 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

### Completion Criteria/Checklist:

To pass this lab, you must finish tasks 1 and 2.

• (Task 1) Declare a derived class Circle from Ellipse in shapes.h and implement the necessary functions inside of shapes.cpp. Don’t override any member functions.

• (Task 2) Declare a derived class Rectangle from Shape in shapes.h and implement the necessary functions inside of shapes.cpp. Override both area and draw.

## Lab Exercises

### The Files

$wget eecs280staff.github.io/lab/lab05/starter-files.tar.gz$ tar -xvzf starter-files.tar.gz


Here’s a summary of this lab’s files. You will turn in the bolded ones.

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++11 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?

Start by writing Circle. Here are some things to consider:

• Separate your code into shapes.h and shapes.cpp appropriately.
• Circle should be derived from Ellipse (which itself is derived from Shape).
• The constructor should take in a single double for its radius.
• Remember that a Circle is just a special case of an Ellipse.

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.

Next we will write Rectangle. Again, here are some things to consider:

• Separate your code into shapes.h and shapes.cpp appropriately.
• Rectangle should be derived directly from Shape.
• The constructor should take in two doubles for its width and height, respectively.
• You need to declare additional member variables to store the width and height.
• You need to override both area and draw, because they are pure virtual in Shape.
• For draw, follow the same structure used in Ellipse: check every pixel in the Canvas 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 Ellipses you will also need to change the type of the array to hold Shape pointers.

## Submit

Submit the required files to the autograder.